mirror of
https://github.com/moodle/moodle.git
synced 2025-03-14 04:30:15 +01:00
MDL-35418 SCORM: Improve SCORM 2004 support
GSOC project to improve SCORM 2004 support, includes MDL-32835 rewrite scorm_get_toc
This commit is contained in:
parent
ecfe814e0f
commit
41e205cd8e
@ -62,7 +62,7 @@ if (confirm_sesskey() && (!empty($scoid))) {
|
||||
}
|
||||
if (substr($element, 0, 15) == 'adl.nav.request') {
|
||||
// SCORM 2004 Sequencing Request
|
||||
require_once($CFG->dirroot.'/mod/scorm/datamodels/sequencinglib.php');
|
||||
require_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_13lib.php');
|
||||
|
||||
$search = array('@continue@', '@previous@', '@\{target=(\S+)\}choice@', '@exit@', '@exitAll@', '@abandon@', '@abandonAll@');
|
||||
$replace = array('continue_', 'previous_', '\1', 'exit_', 'exitall_', 'abandon_', 'abandonall');
|
||||
|
@ -234,13 +234,13 @@ require_once($CFG->dirroot.'/mod/scorm/datamodels/callback.js.php');
|
||||
result = StoreData(cmi,true);
|
||||
if (nav.event != '') {
|
||||
if (nav.event == 'continue') {
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
} else {
|
||||
setTimeout('scorm_get_prev();',500);
|
||||
setTimeout('mod_scorm_launch_prev_sco();',500);
|
||||
}
|
||||
} else {
|
||||
if (<?php echo $scorm->auto ?> == 1) {
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
}
|
||||
}
|
||||
// trigger TOC update
|
||||
|
@ -53,7 +53,7 @@
|
||||
startNode = el_new_tree;
|
||||
}
|
||||
//var sXML = new XMLSerializer().serializeToString(startNode);
|
||||
scorm_tree_node.buildTreeFromMarkup(startNode);
|
||||
scorm_tree_node.buildTreeFromMarkup('scormtree123');
|
||||
var el = document.getElementById('scormtree123');
|
||||
el.parentNode.removeChild(el);
|
||||
scorm_tree_node.expandAll();
|
||||
|
@ -211,13 +211,13 @@ function SCORMapi1_2() {
|
||||
result = StoreData(cmi,true);
|
||||
if (nav.event != '') {
|
||||
if (nav.event == 'continue') {
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
} else {
|
||||
setTimeout('scorm_get_prev();',500);
|
||||
setTimeout('mod_scorm_launch_prev_sco();',500);
|
||||
}
|
||||
} else {
|
||||
if (<?php echo $scorm->auto ?> == 1) {
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
@ -102,7 +102,7 @@ function SCORMapi1_3() {
|
||||
var CMIExit = '^time-out$|^suspend$|^logout$|^normal$|^$';
|
||||
var CMIType = '^true-false$|^choice$|^(long-)?fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$|^other$';
|
||||
var CMIResult = '^correct$|^incorrect$|^unanticipated$|^neutral$|^-?([0-9]{1,4})(\\.[0-9]{1,18})?$';
|
||||
var NAVEvent = '^previous$|^continue$|^exit$|^exitAll$|^abandon$|^abandonAll$|^suspendAll$|^{target=\\S{0,200}[a-zA-Z0-9]}choice$';
|
||||
var NAVEvent = '^previous$|^continue$|^exit$|^exitAll$|^abandon$|^abandonAll$|^suspendAll$|^\{target=\\S{0,200}[a-zA-Z0-9]\}choice|jump$';
|
||||
var NAVBoolean = '^unknown$|^true$|^false$';
|
||||
var NAVTarget = '^previous$|^continue$|^choice.{target=\\S{0,200}[a-zA-Z0-9]}$'
|
||||
// Children lists
|
||||
@ -343,10 +343,10 @@ function SCORMapi1_3() {
|
||||
if (adl.nav.request != '_none_') {
|
||||
switch (adl.nav.request) {
|
||||
case 'continue':
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
break;
|
||||
case 'previous':
|
||||
setTimeout('scorm_get_prev();',500);
|
||||
setTimeout('mod_scorm_launch_prev_sco();',500);
|
||||
break;
|
||||
case 'choice':
|
||||
break;
|
||||
@ -361,7 +361,7 @@ function SCORMapi1_3() {
|
||||
}
|
||||
} else {
|
||||
if (<?php echo $scorm->auto ?> == 1) {
|
||||
setTimeout('scorm_get_next();',500);
|
||||
setTimeout('mod_scorm_launch_next_sco();',500);
|
||||
}
|
||||
}
|
||||
// trigger TOC update
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -275,6 +275,17 @@ function scorm_get_manifest($blocks, $scoes) {
|
||||
$scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptprogressinfo = $sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'] == 'true'?1:0;
|
||||
}
|
||||
}
|
||||
if ($sequencing['name'] == 'IMSSS:DELIVERYCONTROLS') {
|
||||
if (isset($sequencing['attrs']['TRACKED'])) {
|
||||
$scoes->elements[$manifest][$parent->organization][$parent->identifier]->tracked = $sequencing['attrs']['TRACKED'] == 'true'?1:0;
|
||||
}
|
||||
if (isset($sequencing['attrs']['COMPLETIONSETBYCONTENT'])) {
|
||||
$scoes->elements[$manifest][$parent->organization][$parent->identifier]->completionsetbycontent = $sequencing['attrs']['COMPLETIONSETBYCONTENT'] == 'true'?1:0;
|
||||
}
|
||||
if (isset($sequencing['attrs']['OBJECTIVESETBYCONTENT'])) {
|
||||
$scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectivesetbycontent = $sequencing['attrs']['OBJECTIVESETBYCONTENT'] == 'true'?1:0;
|
||||
}
|
||||
}
|
||||
if ($sequencing['name']=='ADLSEQ:CONSTRAINEDCHOICECONSIDERATIONS') {
|
||||
if (isset($sequencing['attrs']['CONSTRAINCHOICE'])) {
|
||||
$scoes->elements[$manifest][$parent->organization][$parent->identifier]->constrainChoice = $sequencing['attrs']['CONSTRAINCHOICE'] == 'true'?1:0;
|
||||
@ -564,6 +575,7 @@ function scorm_parse_scorm($scorm, $manifest) {
|
||||
$rulecond->ruleconditionsid = $ruleid;
|
||||
$rulecond->referencedobjective = $rulecondition->referencedobjective;
|
||||
$rulecond->measurethreshold = $rulecondition->measurethreshold;
|
||||
$rulecond->operator = $rulecondition->operator;
|
||||
$rulecond->cond = $rulecondition->cond;
|
||||
$rulecondid = $DB->insert_record('scorm_seq_rulecond', $rulecond);
|
||||
}
|
||||
@ -669,7 +681,7 @@ function scorm_optionals_data($item, $standarddata) {
|
||||
function scorm_is_leaf($sco) {
|
||||
global $DB;
|
||||
|
||||
if ($DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) {
|
||||
if ($DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -695,16 +707,17 @@ function scorm_get_children($sco) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function scorm_get_available_children($sco) { // TODO: undefined vars!!!
|
||||
function scorm_get_available_children($sco) {
|
||||
global $DB;
|
||||
|
||||
$res = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,
|
||||
'userid'=>$userid,
|
||||
'element'=>'availablechildren'));
|
||||
$res = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier));
|
||||
if (!$res || $res == null) {
|
||||
return false;
|
||||
} else {
|
||||
return unserialize($res->value);
|
||||
foreach ($res as $sco) {
|
||||
$result[] = $sco;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -752,16 +765,16 @@ function scorm_get_ancestors($sco) {
|
||||
return $ancestors;
|
||||
}
|
||||
|
||||
function scorm_get_preorder($preorder=array(), $sco) {
|
||||
function scorm_get_preorder(&$preorder = array(), $sco = null) {
|
||||
if ($sco != null) {
|
||||
array_push($preorder, $sco);
|
||||
$children = scorm_get_children($sco);
|
||||
foreach ($children as $child) {
|
||||
scorm_get_preorder($sco);
|
||||
if ($children = scorm_get_children($sco)) {
|
||||
foreach ($children as $child) {
|
||||
scorm_get_preorder($preorder, $child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $preorder;
|
||||
}
|
||||
return $preorder;
|
||||
}
|
||||
|
||||
function scorm_find_common_ancestor($ancestors, $sco) {
|
||||
|
74
mod/scorm/datamodels/sequencinghandler.php
Normal file
74
mod/scorm/datamodels/sequencinghandler.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once($CFG->dirroot.'/mod/scorm/locallib.php');
|
||||
|
||||
$id = optional_param('id', '', PARAM_INT); // Course Module ID, or
|
||||
$a = optional_param('a', '', PARAM_INT); // scorm ID
|
||||
$scoid = required_param('scoid', PARAM_INT); // sco ID
|
||||
$attempt = required_param('attempt', PARAM_INT); // attempt number
|
||||
$function = required_param('function', PARAM_RAW); // function to call
|
||||
$request = optional_param('request', '', PARAM_RAW); // scorm ID
|
||||
|
||||
if (!empty($id)) {
|
||||
if (! $cm = get_coursemodule_from_id('scorm', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
if (! $course = $DB->get_record("course", array("id"=>$cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
if (! $scorm = $DB->get_record("scorm", array("id"=>$cm->instance))) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
} else if (!empty($a)) {
|
||||
if (! $scorm = $DB->get_record("scorm", array("id"=>$a))) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
if (! $course = $DB->get_record("course", array("id"=>$scorm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
} else {
|
||||
print_error('missingparameter');
|
||||
}
|
||||
|
||||
$PAGE->set_url('/mod/scorm/datamodels/sequencinghandler.php', array('scoid'=>$scoid, 'attempt'=>$attempt, 'id'=>$cm->id, 'function' => $function, 'request' => $request));
|
||||
|
||||
require_login($course, false, $cm);
|
||||
|
||||
if (!empty($scoid) && !empty($function)) {
|
||||
require_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_13lib.php');
|
||||
|
||||
if (has_capability('mod/scorm:savetrack', get_context_instance(CONTEXT_MODULE, $cm->id))) {
|
||||
$result = null;
|
||||
switch ($function) {
|
||||
case 'scorm_seq_flow' :
|
||||
if ($request == 'forward' || $request == 'backward') {
|
||||
$seq = scorm_seq_navigation ($scoid, $USER->id, $request.'_', $attempt);
|
||||
$sco = scorm_get_sco($scoid);
|
||||
$seq = scorm_seq_flow($sco, $request, $seq, true, $USER->id);
|
||||
if (!empty($seq->nextactivity)) {
|
||||
scorm_seq_end_attempt($sco, $USER->id, $seq);
|
||||
}
|
||||
}
|
||||
echo json_encode($seq);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -85,7 +85,17 @@ if (!$sco = scorm_get_sco($scoid)) {
|
||||
print_error('cannotfindsco', 'scorm');
|
||||
}
|
||||
if (scorm_version_check($scorm->version, SCORM_13)) {
|
||||
$userdata->{'cmi.scaled_passing_score'} = $DB->get_field('scorm_seq_objective', 'minnormalizedmeasure', array('scoid'=>$scoid));
|
||||
$objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$scoid));
|
||||
$index = 0;
|
||||
foreach ($objectives as $objective) {
|
||||
if (!empty($objective->minnormalizedmeasure)) {
|
||||
$userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure;
|
||||
}
|
||||
if (!empty($objective->objectiveid)) {
|
||||
$userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid;
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: text/javascript; charset=UTF-8');
|
||||
|
@ -417,6 +417,58 @@ function scorm_insert_track($userid, $scormid, $scoid, $attempt, $element, $valu
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($element == 'cmi.success_status') && ($value == 'passed' || $value == 'failed')) {
|
||||
if ($DB->get_record('scorm_scoes_data', array('scoid'=>$scoid, 'name'=>'objectivesetbycontent'))) {
|
||||
$objectiveprogressstatus = true;
|
||||
$objectivesatisfiedstatus = false;
|
||||
if ($value == 'passed') {
|
||||
$objectivesatisfiedstatus = true;
|
||||
}
|
||||
|
||||
if ($track = $DB->get_record('scorm_scoes_track', array('userid'=>$userid, 'scormid'=>$scormid, 'scoid'=>$scoid, 'attempt'=>$attempt, 'element'=>'objectiveprogressstatus'))) {
|
||||
$track->value = $objectiveprogressstatus;
|
||||
$track->timemodified = time();
|
||||
$DB->update_record('scorm_scoes_track', $track);
|
||||
$id = $track->id;
|
||||
} else {
|
||||
$track = new stdClass();
|
||||
$track->userid = $userid;
|
||||
$track->scormid = $scormid;
|
||||
$track->scoid = $scoid;
|
||||
$track->attempt = $attempt;
|
||||
$track->element = 'objectiveprogressstatus';
|
||||
$track->value = $objectiveprogressstatus;
|
||||
$track->timemodified = time();
|
||||
$id = $DB->insert_record('scorm_scoes_track', $track);
|
||||
}
|
||||
if ($objectivesatisfiedstatus) {
|
||||
if ($track = $DB->get_record('scorm_scoes_track', array('userid'=>$userid, 'scormid'=>$scormid, 'scoid'=>$scoid, 'attempt'=>$attempt, 'element'=>'objectivesatisfiedstatus'))) {
|
||||
$track->value = $objectivesatisfiedstatus;
|
||||
$track->timemodified = time();
|
||||
$DB->update_record('scorm_scoes_track', $track);
|
||||
$id = $track->id;
|
||||
} else {
|
||||
$track = new stdClass();
|
||||
$track->userid = $userid;
|
||||
$track->scormid = $scormid;
|
||||
$track->scoid = $scoid;
|
||||
$track->attempt = $attempt;
|
||||
$track->element = 'objectivesatisfiedstatus';
|
||||
$track->value = $objectivesatisfiedstatus;
|
||||
$track->timemodified = time();
|
||||
$id = $DB->insert_record('scorm_scoes_track', $track);
|
||||
ob_start();
|
||||
$filepath = $CFG->dataroot."\\temp\\tempfile.txt";
|
||||
$fh = fopen($filepath, "a+");
|
||||
var_dump($track);
|
||||
$string = ob_get_clean();
|
||||
fwrite($fh, $string);
|
||||
fclose($fh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($track = $DB->get_record('scorm_scoes_track', array('userid'=>$userid, 'scormid'=>$scormid, 'scoid'=>$scoid, 'attempt'=>$attempt, 'element'=>$element))) {
|
||||
@ -479,7 +531,6 @@ function scorm_get_tracks($scoid, $userid, $attempt='') {
|
||||
// Defined in order to unify scorm1.2 and scorm2004
|
||||
$usertrack->score_raw = '';
|
||||
$usertrack->status = '';
|
||||
$usertrack->progress = '';
|
||||
$usertrack->total_time = '00:00:00';
|
||||
$usertrack->session_time = '00:00:00';
|
||||
$usertrack->timemodified = 0;
|
||||
@ -493,35 +544,19 @@ function scorm_get_tracks($scoid, $userid, $attempt='') {
|
||||
$track->value = 'notattempted';
|
||||
}
|
||||
$usertrack->status = $track->value;
|
||||
break;
|
||||
case 'cmi.success_status':
|
||||
$usertrack->progress = $track->value;
|
||||
break;
|
||||
case 'cmi.progress_measure':
|
||||
if (!empty($track->value) && (empty($usertrack->progress) || $usertrack->progress == 'unknown') ) {
|
||||
$usertrack->progress = $track->value;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'cmi.core.score.raw':
|
||||
case 'cmi.score.raw':
|
||||
$usertrack->score_raw = (float) sprintf('%2.2f', $track->value);
|
||||
break;
|
||||
case 'cmi.core.score.max':
|
||||
case 'cmi.score.max':
|
||||
$usertrack->score_max = (float) sprintf('%2.2f', $track->value);
|
||||
break;
|
||||
case 'cmi.core.score.min':
|
||||
case 'cmi.score.min':
|
||||
$usertrack->score_min = (float) sprintf('%2.2f', $track->value);
|
||||
break;
|
||||
break;
|
||||
case 'cmi.core.session_time':
|
||||
case 'cmi.session_time':
|
||||
$usertrack->session_time = $track->value;
|
||||
break;
|
||||
break;
|
||||
case 'cmi.core.total_time':
|
||||
case 'cmi.total_time':
|
||||
$usertrack->total_time = $track->value;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
if (isset($track->timemodified) && ($track->timemodified > $usertrack->timemodified)) {
|
||||
$usertrack->timemodified = $track->timemodified;
|
||||
@ -1330,7 +1365,7 @@ function scorm_format_duration($duration) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$scoid='',$mode='normal',$attempt='',$play=false, $tocheader=false) {
|
||||
function scorm_get_toc_object($user, $scorm, $currentorg='', $scoid='', $mode='normal', $attempt='', $play=false, $organizationsco=null) {
|
||||
global $CFG, $DB, $PAGE, $OUTPUT;
|
||||
|
||||
$modestr = '';
|
||||
@ -1338,47 +1373,22 @@ function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$sco
|
||||
$modestr = '&mode='.$mode;
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
if ($tocheader) {
|
||||
$result->toc = '<div id="scorm_layout">';
|
||||
$result->toc .= '<div id="scorm_toc">';
|
||||
$result->toc .= '<div id="scorm_tree">';
|
||||
}
|
||||
$result->toc .= '<ul>';
|
||||
$tocmenus = array();
|
||||
$result->prerequisites = true;
|
||||
$result = array();
|
||||
$incomplete = false;
|
||||
|
||||
//
|
||||
// Get the current organization infos
|
||||
//
|
||||
if (!empty($currentorg)) {
|
||||
if (($organizationtitle = $DB->get_field('scorm_scoes','title', array('scorm'=>$scorm->id,'identifier'=>$currentorg))) != '') {
|
||||
if ($play) {
|
||||
$result->toctitle = "$organizationtitle";
|
||||
}
|
||||
else {
|
||||
$result->toc .= "\t<li>$organizationtitle</li>\n";
|
||||
}
|
||||
$tocmenus[] = $organizationtitle;
|
||||
}
|
||||
if (!empty($organizationsco)) {
|
||||
$result[0] = $organizationsco;
|
||||
$result[0]->isvisible = true;
|
||||
$result[0]->statusicon = '';
|
||||
$result[0]->url = '';
|
||||
}
|
||||
|
||||
//
|
||||
// If not specified retrieve the last attempt number
|
||||
//
|
||||
if (empty($attempt)) {
|
||||
$attempt = scorm_get_attempt_count($user->id, $scorm);
|
||||
}
|
||||
$result->attemptleft = $scorm->maxattempt == 0 ? 1 : $scorm->maxattempt - $attempt;
|
||||
if ($scoes = scorm_get_scoes($scorm->id, $currentorg)){
|
||||
//
|
||||
// Retrieve user tracking data for each learning object
|
||||
//
|
||||
// Retrieve user tracking data for each learning object.
|
||||
$usertracks = array();
|
||||
foreach ($scoes as $sco) {
|
||||
if (!empty($sco->launch)) {
|
||||
if ($usertrack = scorm_get_tracks($sco->id,$user->id,$attempt)) {
|
||||
if ($usertrack = scorm_get_tracks($sco->id,$user->id, $attempt)) {
|
||||
if ($usertrack->status == '') {
|
||||
$usertrack->status = 'notattempted';
|
||||
}
|
||||
@ -1386,80 +1396,36 @@ function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$sco
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($scoes as $sco) {
|
||||
if (!isset($sco->isvisible)) {
|
||||
$sco->isvisible = true;
|
||||
}
|
||||
|
||||
$level=0;
|
||||
$sublist=1;
|
||||
$previd = 0;
|
||||
$nextid = 0;
|
||||
$findnext = false;
|
||||
$parents[$level]='/';
|
||||
$prevsco = '';
|
||||
foreach ($scoes as $pos => $sco) {
|
||||
$isvisible = false;
|
||||
$sco->title = $sco->title;
|
||||
if (!isset($sco->isvisible) || (isset($sco->isvisible) && ($sco->isvisible == 'true'))) {
|
||||
$isvisible = true;
|
||||
}
|
||||
if ($parents[$level] != $sco->parent) {
|
||||
$newlevel = array_search($sco->parent,$parents);
|
||||
if ($newlevel !== false) {
|
||||
for ($i=0; $i<($level-$newlevel); $i++) {
|
||||
$result->toc .= "\t\t</li></ul></li>\n";
|
||||
}
|
||||
$level = $newlevel;
|
||||
} else {
|
||||
$i = $level;
|
||||
$closelist = '';
|
||||
while (($i > 0) && ($parents[$level] != $sco->parent)) {
|
||||
if ($i === 1 && $level > 1) {
|
||||
$closelist .= "\t\t</ul></li>\n";
|
||||
} else {
|
||||
$closelist .= "\t</li></ul></li>\n";
|
||||
}
|
||||
$i--;
|
||||
}
|
||||
if (($i == 0) && ($sco->parent != $currentorg)) {
|
||||
$result->toc .= "\n\t<ul>\n";
|
||||
$level++;
|
||||
} else {
|
||||
$result->toc .= $closelist;
|
||||
$level = $i;
|
||||
}
|
||||
$parents[$level] = $sco->parent;
|
||||
}
|
||||
}
|
||||
if ($isvisible) {
|
||||
$result->toc .= "<li>";
|
||||
}
|
||||
if (isset($scoes[$pos+1])) {
|
||||
$nextsco = $scoes[$pos+1];
|
||||
} else {
|
||||
$nextsco = false;
|
||||
}
|
||||
$nextisvisible = false;
|
||||
if (($nextsco !== false) && (!isset($nextsco->isvisible) || (isset($nextsco->isvisible) && ($nextsco->isvisible == 'true')))) {
|
||||
$nextisvisible = true;
|
||||
}
|
||||
if ($nextisvisible && ($nextsco !== false) && ($sco->parent != $nextsco->parent) &&
|
||||
(($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) {
|
||||
$sublist++;
|
||||
}
|
||||
if (empty($sco->title)) {
|
||||
$sco->title = $sco->identifier;
|
||||
}
|
||||
if ($isvisible) {
|
||||
|
||||
if (scorm_version_check($scorm->version, SCORM_13)) {
|
||||
require_once($CFG->dirroot.'/mod/scorm/datamodels/sequencinglib.php');
|
||||
$sco->prereq = scorm_seq_evaluate($sco->id, $usertracks);
|
||||
} else {
|
||||
$sco->prereq = empty($sco->prerequisites) || scorm_eval_prerequisites($sco->prerequisites, $usertracks);
|
||||
}
|
||||
|
||||
if ($sco->isvisible) {
|
||||
if (!empty($sco->launch)) {
|
||||
$score = '';
|
||||
if (empty($scoid) && ($mode != 'normal')) {
|
||||
$scoid = $sco->id;
|
||||
}
|
||||
|
||||
if (isset($usertracks[$sco->identifier])) {
|
||||
$usertrack = $usertracks[$sco->identifier];
|
||||
$strstatus = get_string($usertrack->status,'scorm');
|
||||
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url($usertrack->status, 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" />';
|
||||
} else {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('assetc', 'scorm').'" alt="'.get_string('assetlaunched','scorm').'" title="'.get_string('assetlaunched','scorm').'" />';
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('assetlaunched', 'scorm').'" title="'.get_string('assetlaunched', 'scorm').'" />';
|
||||
}
|
||||
|
||||
if (($usertrack->status == 'notattempted') || ($usertrack->status == 'incomplete') || ($usertrack->status == 'browsed')) {
|
||||
@ -1468,114 +1434,422 @@ function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$sco
|
||||
$scoid = $sco->id;
|
||||
}
|
||||
}
|
||||
if ($usertrack->score_raw != '' && has_capability('mod/scorm:viewscores', context_module::instance($cmid))) {
|
||||
$score = '('.get_string('score','scorm').': '.$usertrack->score_raw.')';
|
||||
}
|
||||
$strsuspended = get_string('suspended','scorm');
|
||||
|
||||
$strsuspended = get_string('suspended', 'scorm');
|
||||
|
||||
$exitvar = 'cmi.core.exit';
|
||||
|
||||
if (scorm_version_check($scorm->version, SCORM_13)) {
|
||||
$exitvar = 'cmi.exit';
|
||||
}
|
||||
|
||||
if ($incomplete && isset($usertrack->{$exitvar}) && ($usertrack->{$exitvar} == 'suspend')) {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('suspend', 'scorm').'" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />';
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($play && empty($scoid)) {
|
||||
$scoid = $sco->id;
|
||||
}
|
||||
$incomplete = true;
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted','scorm').'" title="'.get_string('notattempted','scorm').'" />';
|
||||
} else {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('asset','scorm').'" title="'.get_string('asset','scorm').'" />';
|
||||
}
|
||||
}
|
||||
if ($sco->id == $scoid) {
|
||||
$findnext = true;
|
||||
}
|
||||
|
||||
if (($nextid == 0) && (scorm_count_launchable($scorm->id,$currentorg) > 1) && ($nextsco!==false) && (!$findnext)) {
|
||||
if (!empty($sco->launch)) {
|
||||
$previd = $sco->id;
|
||||
}
|
||||
}
|
||||
if (scorm_version_check($scorm->version, SCORM_13)) {
|
||||
require_once($CFG->dirroot.'/mod/scorm/datamodels/sequencinglib.php');
|
||||
$prereq = scorm_seq_evaluate($sco->id,$usertracks);
|
||||
} else {
|
||||
//TODO: split check for sco->prerequisites only for AICC as I think that's the only case it's set.
|
||||
$prereq = empty($sco->prerequisites) || scorm_eval_prerequisites($sco->prerequisites,$usertracks);
|
||||
}
|
||||
if ($prereq) {
|
||||
if ($sco->id == $scoid) {
|
||||
$result->prerequisites = true;
|
||||
}
|
||||
if (!empty($prevsco) && scorm_version_check($scorm->version, SCORM_13) && !empty($prevsco->hidecontinue)) {
|
||||
$result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>';
|
||||
} else if ($toclink == TOCFULLURL) { //display toc with urls for structure page
|
||||
$url = $CFG->wwwroot.'/mod/scorm/player.php?a='.$scorm->id.'&currentorg='.$currentorg.$modestr.'&scoid='.$sco->id;
|
||||
$result->toc .= $statusicon.' <a href="'.$url.'">'.format_string($sco->title).'</a>'.$score."\n";
|
||||
} else { //display toc for inside scorm player
|
||||
if ($sco->launch) {
|
||||
$link = 'a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$currentorg.$modestr.'&attempt='.$attempt;
|
||||
$result->toc .= '<a title="'.$link.'">'.$statusicon.' '.format_string($sco->title).' '.$score.'</a>';
|
||||
} else {
|
||||
$result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>';
|
||||
}
|
||||
}
|
||||
$tocmenus[$sco->id] = scorm_repeater('−',$level) . '>' . format_string($sco->title);
|
||||
} else {
|
||||
if ($sco->id == $scoid) {
|
||||
$result->prerequisites = false;
|
||||
}
|
||||
if ($play) {
|
||||
// should be disabled
|
||||
$result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>';
|
||||
$incomplete = true;
|
||||
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted', 'scorm').'" title="'.get_string('notattempted', 'scorm').'" />';
|
||||
} else {
|
||||
$result->toc .= $statusicon.' '.format_string($sco->title)."\n";
|
||||
$statusicon = '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('asset', 'scorm').'" title="'.get_string('asset', 'scorm').'" />';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result->toc .= ' '.format_string($sco->title);
|
||||
}
|
||||
if (($nextsco === false) || $nextsco->parent == $sco->parent) {
|
||||
$result->toc .= "</li>\n";
|
||||
}
|
||||
}
|
||||
if (($nextsco !== false) && ($nextid == 0) && ($findnext)) {
|
||||
if (!empty($nextsco->launch)) {
|
||||
$nextid = $nextsco->id;
|
||||
|
||||
if (empty($statusicon)) {
|
||||
$sco->statusicon = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted', 'scorm').'" title="'.get_string('notattempted', 'scorm').'" />';
|
||||
} else {
|
||||
$sco->statusicon = $statusicon;
|
||||
}
|
||||
|
||||
$sco->url = 'a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$currentorg.$modestr.'&attempt='.$attempt;
|
||||
$sco->incomplete = $incomplete;
|
||||
|
||||
if (!in_array($sco->id, array_keys($result))) {
|
||||
$result[$sco->id] = $sco;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the parent scoes!
|
||||
$result = scorm_get_toc_get_parent_child($result);
|
||||
|
||||
// Be safe, prevent warnings from showing up while returning array
|
||||
if (!isset($scoid)) {
|
||||
$scoid = '';
|
||||
}
|
||||
|
||||
return array('scoes' => $result, 'usertracks' => $usertracks, 'scoid' => $scoid);
|
||||
}
|
||||
|
||||
function scorm_get_toc_get_parent_child(&$result) {
|
||||
$final = array();
|
||||
$level = 0;
|
||||
$prevparent = '/';
|
||||
ksort($result);
|
||||
|
||||
foreach ($result as $sco) {
|
||||
if ($sco->parent == '/') {
|
||||
$final[$level][$sco->identifier] = $sco;
|
||||
$prevparent = $sco->identifier;
|
||||
unset($result[$sco->id]);
|
||||
} else {
|
||||
if ($sco->parent == $prevparent) {
|
||||
$final[$level][$sco->identifier] = $sco;
|
||||
$prevparent = $sco->identifier;
|
||||
unset($result[$sco->id]);
|
||||
} else {
|
||||
if (!empty($final[$level])) {
|
||||
$found = false;
|
||||
foreach ($final[$level] as $fin) {
|
||||
if ($sco->parent == $fin->identifier) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
$final[$level][$sco->identifier] = $sco;
|
||||
unset($result[$sco->id]);
|
||||
$found = false;
|
||||
} else {
|
||||
$level++;
|
||||
$final[$level][$sco->identifier] = $sco;
|
||||
unset($result[$sco->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= $level; $i++) {
|
||||
$prevparent = '';
|
||||
foreach ($final[$i] as $ident => $sco) {
|
||||
if (empty($prevparent)) {
|
||||
$prevparent = $ident;
|
||||
}
|
||||
|
||||
if ($sco->parent == $prevparent) {
|
||||
if (!isset($final[$i][$prevparent]->children)) {
|
||||
$final[$i][$prevparent]->children = array();
|
||||
}
|
||||
$final[$i][$prevparent]->children[] = $sco;
|
||||
$prevparent = $ident;
|
||||
} else {
|
||||
$parent = false;
|
||||
foreach ($final[$i] as $identifier => $scoobj) {
|
||||
if ($identifier == $sco->parent) {
|
||||
$parent = $identifier;
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent !== false) {
|
||||
$final[$i][$parent]->children[] = $sco;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = array();
|
||||
for ($i = 0; $i <= $level; $i++) {
|
||||
$keys = array_keys($final[$i]);
|
||||
$results[] = $final[$i][$keys[0]];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
function scorm_format_toc_for_treeview($user, $scorm, $scoes, $usertracks, $cmid, $toclink=TOCJSLINK, $currentorg='', $attempt='', $play=false, $organizationsco=null, $children=false) {
|
||||
global $CFG;
|
||||
|
||||
$result = new stdClass();
|
||||
$result->prerequisites = true;
|
||||
|
||||
if (!$children) {
|
||||
$result->attemptleft = $scorm->maxattempt == 0 ? 1 : $scorm->maxattempt - $attempt;
|
||||
}
|
||||
|
||||
if (!$children) {
|
||||
$result->toc = "<ul>\n";
|
||||
|
||||
if (!$play && !empty($organizationsco)) {
|
||||
$result->toc .= "\t<li>".$organizationsco->title."</li>\n";
|
||||
}
|
||||
}
|
||||
|
||||
$prevsco = '';
|
||||
if (!empty($scoes)) {
|
||||
foreach ($scoes as $sco) {
|
||||
$result->toc .= "\t<li>\n";
|
||||
$scoid = $sco->id;
|
||||
|
||||
$sco->isvisible = true;
|
||||
|
||||
if ($sco->isvisible) {
|
||||
$score = '';
|
||||
|
||||
if (isset($usertracks[$sco->identifier])) {
|
||||
$viewscore = has_capability('mod/scorm:viewscores', get_context_instance(CONTEXT_MODULE, $cmid));
|
||||
if (isset($usertracks[$sco->identifier]->score_raw) && $viewscore) {
|
||||
if ($usertracks[$sco->identifier]->score_raw != '') {
|
||||
$score = '('.get_string('score','scorm').': '.$usertracks[$sco->identifier]->score_raw.')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sco->prereq)) {
|
||||
if ($sco->id == $scoid) {
|
||||
$result->prerequisites = true;
|
||||
}
|
||||
|
||||
if (!empty($prevsco) && scorm_version_check($scorm->version, SCORM_13) && !empty($prevsco->hidecontinue)) {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= '<span>'.$sco->statusicon.' '.format_string($sco->title).'</span>';
|
||||
} else {
|
||||
$result->toc .= '<span> '.format_string($sco->title).'</span>';
|
||||
}
|
||||
} else if ($toclink == TOCFULLURL) {
|
||||
$url = $CFG->wwwroot.'/mod/scorm/player.php?'.$sco->url;
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= $sco->statusicon.' <a href="'.$url.'">'.format_string($sco->title).'</a>'.$score."\n";
|
||||
} else {
|
||||
$result->toc .= ' <a href="'.$url.'">'.format_string($sco->title).'</a>'.$score."\n";
|
||||
}
|
||||
} else {
|
||||
if ($sco->launch) {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= '<a title="'.$sco->url.'">'.$sco->statusicon.' '.format_string($sco->title).' '.$score.'</a>';
|
||||
} else {
|
||||
$result->toc .= '<a title="'.$sco->url.'"> '.format_string($sco->title).' '.$score.'</a>';
|
||||
}
|
||||
} else {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= '<span>'.$sco->statusicon.' '.format_string($sco->title).'</span>';
|
||||
} else {
|
||||
$result->toc .= '<span> '.format_string($sco->title).'</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($play) {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= '<span>'.$sco->statusicon.' '.format_string($sco->title).'</span>';
|
||||
} else {
|
||||
$result->toc .= ' '.format_string($sco->title).'</span>';
|
||||
}
|
||||
} else {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$result->toc .= $sco->statusicon.' '.format_string($sco->title)."\n";
|
||||
} else {
|
||||
$result->toc .= ' '.format_string($sco->title)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$result->toc .= "\t\t ".format_string($sco->title)."\n";
|
||||
}
|
||||
|
||||
if (!empty($sco->children)) {
|
||||
$result->toc .= "\n\t\t<ul>\n";
|
||||
$childresult = scorm_format_toc_for_treeview($user, $scorm, $sco->children, $usertracks, $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, true);
|
||||
$result->toc .= $childresult->toc;
|
||||
$result->toc .= "\t\t</ul>\n";
|
||||
$result->toc .= "\t</li>\n";
|
||||
} else {
|
||||
$result->toc .= "\t</li>\n";
|
||||
}
|
||||
$prevsco = $sco;
|
||||
}
|
||||
for ($i=0;$i<$level;$i++) {
|
||||
$result->toc .= "\t\t</ul></li>\n";
|
||||
}
|
||||
|
||||
if ($play) {
|
||||
// it is possible that $scoid is still not set, in this case we don't want an empty object
|
||||
if ($scoid) {
|
||||
$sco = scorm_get_sco($scoid);
|
||||
}
|
||||
$sco->previd = $previd;
|
||||
$sco->nextid = $nextid;
|
||||
$result->sco = $sco;
|
||||
$result->incomplete = $incomplete;
|
||||
} else {
|
||||
$result->incomplete = $incomplete;
|
||||
}
|
||||
}
|
||||
$result->toc .= '</ul>';
|
||||
|
||||
// NEW IMS TOC
|
||||
if ($tocheader) {
|
||||
$result->toc .= '</div></div></div>';
|
||||
$result->toc .= '<div id="scorm_navpanel"></div>';
|
||||
$result->incomplete = $sco->incomplete;
|
||||
}
|
||||
|
||||
$url = new moodle_url('/mod/scorm/player.php?a='.$scorm->id.'¤torg='.$currentorg.$modestr);
|
||||
$result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenus, $sco->id, null, "tocmenu");
|
||||
if (!$children) {
|
||||
$result->toc .= "</ul>\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function scorm_format_toc_for_droplist($scorm, $scoes, $usertracks, $currentorg='', $organizationsco=null, $children=false, $level=0, $tocmenus=array()) {
|
||||
if (!empty($scoes)) {
|
||||
if (!empty($organizationsco) && !$children) {
|
||||
$tocmenus[$organizationsco->id] = $organizationsco->title;
|
||||
}
|
||||
|
||||
$parents[$level]='/';
|
||||
foreach ($scoes as $sco) {
|
||||
if ($parents[$level] != $sco->parent) {
|
||||
if ($newlevel = array_search($sco->parent, $parents)) {
|
||||
$level = $newlevel;
|
||||
} else {
|
||||
$i = $level;
|
||||
while (($i > 0) && ($parents[$level] != $sco->parent)) {
|
||||
$i--;
|
||||
}
|
||||
|
||||
if (($i == 0) && ($sco->parent != $currentorg)) {
|
||||
$level++;
|
||||
} else {
|
||||
$level = $i;
|
||||
}
|
||||
|
||||
$parents[$level] = $sco->parent;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sco->prereq) {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title);
|
||||
}
|
||||
} else {
|
||||
if ($sco->scormtype == 'sco') {
|
||||
$tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sco->children)) {
|
||||
$tocmenus = scorm_format_toc_for_droplist($scorm, $sco->children, $usertracks, $currentorg, $organizationsco, true, $level, $tocmenus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tocmenus;
|
||||
}
|
||||
|
||||
function scorm_get_toc($user, $scorm, $cmid, $toclink=TOCJSLINK, $currentorg='', $scoid='', $mode='normal', $attempt='', $play=false, $tocheader=false) {
|
||||
global $CFG, $DB, $OUTPUT;
|
||||
|
||||
if (empty($attempt)) {
|
||||
$attempt = scorm_get_attempt_count($user->id, $scorm);
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
$organizationsco = null;
|
||||
|
||||
if ($tocheader) {
|
||||
$result->toc = "<div id=\"scorm_layout\">\n";
|
||||
$result->toc .= "<div id=\"scorm_toc\">\n";
|
||||
$result->toc .= "<div id=\"scorm_tree\">\n";
|
||||
}
|
||||
|
||||
if (!empty($currentorg)) {
|
||||
$organizationsco = $DB->get_record('scorm_scoes', array('scorm'=>$scorm->id, 'identifier'=>$currentorg));
|
||||
if (!empty($organizationsco->title)) {
|
||||
if ($play) {
|
||||
$result->toctitle = $organizationsco->title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scoes = scorm_get_toc_object($user, $scorm, $currentorg, $scoid, $mode, $attempt, $play, $organizationsco);
|
||||
|
||||
$treeview = scorm_format_toc_for_treeview($user, $scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, false);
|
||||
|
||||
if ($tocheader) {
|
||||
$result->toc .= $treeview->toc;
|
||||
} else {
|
||||
$result->toc = $treeview->toc;
|
||||
}
|
||||
|
||||
if (!empty($scoes['scoid'])) {
|
||||
$scoid = $scoes['scoid'];
|
||||
}
|
||||
|
||||
if (empty($scoid)) {
|
||||
$result->sco = $scoes['scoes'][0]->children;
|
||||
} else {
|
||||
$result->sco = scorm_get_sco($scoid);
|
||||
}
|
||||
|
||||
if ($scorm->hidetoc == SCORM_TOC_POPUP) {
|
||||
$tocmenu = scorm_format_toc_for_droplist($scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $currentorg, $organizationsco);
|
||||
|
||||
$modestr = '';
|
||||
if ($mode == 'browse') {
|
||||
$modestr = '&mode='.$mode;
|
||||
}
|
||||
|
||||
$url = new moodle_url('/mod/scorm/player.php?a='.$scorm->id.'¤torg='.$currentorg.$modestr);
|
||||
$result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenu, $result->sco->id, null, "tocmenu");
|
||||
}
|
||||
|
||||
$result->prerequisites = $treeview->prerequisites;
|
||||
$result->incomplete = $treeview->incomplete;
|
||||
$result->attemptleft = $treeview->attemptleft;
|
||||
|
||||
if ($tocheader) {
|
||||
$result->toc .= "</div></div></div>\n";
|
||||
$result->toc .= "<div id=\"scorm_navpanel\"></div>\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function scorm_get_adlnav_json ($scoes, &$adlnav = array(), $parentscoid = null) {
|
||||
if (is_object($scoes)) {
|
||||
$sco = $scoes;
|
||||
if (isset($sco->url)) {
|
||||
$adlnav[$sco->id]['identifier'] = $sco->identifier;
|
||||
$adlnav[$sco->id]['launch'] = $sco->launch;
|
||||
$adlnav[$sco->id]['title'] = $sco->title;
|
||||
$adlnav[$sco->id]['url'] = $sco->url;
|
||||
$adlnav[$sco->id]['parent'] = $sco->parent;
|
||||
if (isset($sco->choice)) {
|
||||
$adlnav[$sco->id]['choice'] = $sco->choice;
|
||||
}
|
||||
if (isset($sco->flow)) {
|
||||
$adlnav[$sco->id]['flow'] = $sco->flow;
|
||||
} else if (isset($parentscoid) && isset($adlnav[$parentscoid]['flow'])) {
|
||||
$adlnav[$sco->id]['flow'] = $adlnav[$parentscoid]['flow'];
|
||||
}
|
||||
if (isset($sco->isvisible)) {
|
||||
$adlnav[$sco->id]['isvisible'] = $sco->isvisible;
|
||||
}
|
||||
if (isset($sco->parameters)) {
|
||||
$adlnav[$sco->id]['parameters'] = $sco->parameters;
|
||||
}
|
||||
if (isset($sco->hidecontinue)) {
|
||||
$adlnav[$sco->id]['hidecontinue'] = $sco->hidecontinue;
|
||||
}
|
||||
if (isset($sco->hideprevious)) {
|
||||
$adlnav[$sco->id]['hideprevious'] = $sco->hideprevious;
|
||||
}
|
||||
if (isset($sco->hidesuspendall)) {
|
||||
$adlnav[$sco->id]['hidesuspendall'] = $sco->hidesuspendall;
|
||||
}
|
||||
if (!empty($parentscoid)) {
|
||||
$adlnav[$sco->id]['parentscoid'] = $parentscoid;
|
||||
}
|
||||
if (isset($adlnav['prevscoid'])) {
|
||||
$adlnav[$sco->id]['prevscoid'] = $adlnav['prevscoid'];
|
||||
$adlnav[$adlnav['prevscoid']]['nextscoid'] = $sco->id;
|
||||
if (isset($adlnav['prevparent']) && $adlnav['prevparent'] == $sco->parent) {
|
||||
$adlnav[$sco->id]['prevsibling'] = $adlnav['prevscoid'];
|
||||
$adlnav[$adlnav['prevscoid']]['nextsibling'] = $sco->id;
|
||||
}
|
||||
}
|
||||
$adlnav['prevscoid'] = $sco->id;
|
||||
$adlnav['prevparent'] = $sco->parent;
|
||||
}
|
||||
if (isset($sco->children)) {
|
||||
foreach ($sco->children as $children) {
|
||||
scorm_get_adlnav_json($children, $adlnav, $sco->id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($scoes as $sco) {
|
||||
scorm_get_adlnav_json ($sco, $adlnav);
|
||||
}
|
||||
unset($adlnav['prevscoid']);
|
||||
unset($adlnav['prevparent']);
|
||||
}
|
||||
return json_encode($adlnav);
|
||||
}
|
||||
|
@ -21,13 +21,13 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
mod_scorm_next = null;
|
||||
mod_scorm_prev = null;
|
||||
mod_scorm_launch_next_sco = null;
|
||||
mod_scorm_launch_prev_sco = null;
|
||||
mod_scorm_activate_item = null;
|
||||
|
||||
M.mod_scorm = {};
|
||||
|
||||
M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launch_sco) {
|
||||
M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launch_sco, scoes_nav) {
|
||||
var scorm_disable_toc = false;
|
||||
var scorm_hide_nav = true;
|
||||
var scorm_hide_toc = true;
|
||||
@ -40,6 +40,7 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
scorm_disable_toc = true;
|
||||
}
|
||||
|
||||
scoes_nav = JSON.parse(scoes_nav);
|
||||
var scorm_layout_widget;
|
||||
var scorm_current_node;
|
||||
var scorm_buttons = [];
|
||||
@ -166,11 +167,15 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
* @return void
|
||||
*/
|
||||
var scorm_fixnav = function() {
|
||||
scorm_buttons[0].set('disabled', (scorm_skipprev(scorm_current_node) == null || scorm_skipprev(scorm_current_node).title == null));
|
||||
scorm_buttons[1].set('disabled', (scorm_prev(scorm_current_node) == null || scorm_prev(scorm_current_node).title == null));
|
||||
scorm_buttons[0].set('disabled', (scorm_skipprev(scorm_current_node) == null || scorm_skipprev(scorm_current_node).title == null ||
|
||||
scoes_nav[launch_sco].hideprevious == 1));
|
||||
scorm_buttons[1].set('disabled', (scorm_prev(scorm_current_node) == null || scorm_prev(scorm_current_node).title == null ||
|
||||
scoes_nav[launch_sco].hideprevious == 1));
|
||||
scorm_buttons[2].set('disabled', (scorm_up(scorm_current_node) == null) || scorm_up(scorm_current_node).title == null);
|
||||
scorm_buttons[3].set('disabled', (scorm_next(scorm_current_node) == null) || scorm_next(scorm_current_node).title == null);
|
||||
scorm_buttons[4].set('disabled', (scorm_skipnext(scorm_current_node) == null || scorm_skipnext(scorm_current_node).title == null));
|
||||
scorm_buttons[3].set('disabled', (((scorm_next(scorm_current_node) == null || scorm_next(scorm_current_node).title == null) &&
|
||||
(scoes_nav[launch_sco].flow != 1)) || (scoes_nav[launch_sco].hidecontinue == 1)));
|
||||
scorm_buttons[4].set('disabled', (scorm_skipnext(scorm_current_node) == null || scorm_skipnext(scorm_current_node).title == null ||
|
||||
scoes_nav[launch_sco].hidecontinue == 1));
|
||||
};
|
||||
|
||||
var scorm_resize_parent = function() {
|
||||
@ -253,9 +258,21 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
}
|
||||
};
|
||||
|
||||
var scorm_up = function(node) {
|
||||
// Handle AJAX Request
|
||||
var scorm_ajax_request = function(url, datastring) {
|
||||
var myRequest = NewHttpReq();
|
||||
var result = DoRequest(myRequest, url + datastring);
|
||||
return result;
|
||||
};
|
||||
|
||||
var scorm_up = function(node, update_launch_sco) {
|
||||
var node = scorm_tree_node.getHighlightedNode();
|
||||
if (node.depth > 0) {
|
||||
if (node.depth > 0 && typeof scoes_nav[launch_sco].parentscoid != 'undefined') {
|
||||
var parentscoid = scoes_nav[launch_sco].parentscoid;
|
||||
node.parent.title = scoes_nav[parentscoid].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = parentscoid;
|
||||
}
|
||||
return node.parent;
|
||||
}
|
||||
return null;
|
||||
@ -269,43 +286,131 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
}
|
||||
};
|
||||
|
||||
var scorm_prev = function(node) {
|
||||
if (node.previousSibling && node.previousSibling.children.length) {
|
||||
return scorm_lastchild(node.previousSibling);
|
||||
var scorm_prev = function(node, update_launch_sco) {
|
||||
if (node.previousSibling && node.previousSibling.children.length &&
|
||||
typeof scoes_nav[launch_sco].prevscoid != 'undefined') {
|
||||
var node = scorm_lastchild(node.previousSibling);
|
||||
if (node) {
|
||||
var prevscoid = scoes_nav[launch_sco].prevscoid;
|
||||
node.title = scoes_nav[prevscoid].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = prevscoid;
|
||||
}
|
||||
return node;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return scorm_skipprev(node);
|
||||
return scorm_skipprev(node, update_launch_sco);
|
||||
};
|
||||
|
||||
var scorm_skipprev = function(node) {
|
||||
if (node.previousSibling) {
|
||||
var scorm_skipprev = function(node, update_launch_sco) {
|
||||
if (node.previousSibling && typeof scoes_nav[launch_sco].prevsibling != 'undefined') {
|
||||
var prevsibling = scoes_nav[launch_sco].prevsibling;
|
||||
node.previousSibling.title = scoes_nav[prevsibling].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = prevsibling;
|
||||
}
|
||||
return node.previousSibling;
|
||||
} else if (node.depth > 0) {
|
||||
} else if (node.depth > 0 && typeof scoes_nav[launch_sco].parentscoid != 'undefined') {
|
||||
var parentscoid = scoes_nav[launch_sco].parentscoid;
|
||||
node.parent.title = scoes_nav[parentscoid].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = parentscoid;
|
||||
}
|
||||
return node.parent;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var scorm_next = function(node) {
|
||||
var scorm_next = function(node, update_launch_sco) {
|
||||
if (node === false) {
|
||||
return scorm_tree_node.getRoot().children[0];
|
||||
}
|
||||
if (node.children.length) {
|
||||
return node.children[0];
|
||||
if (node.children.length && typeof scoes_nav[launch_sco].nextscoid != 'undefined') {
|
||||
var node = node.children[0];
|
||||
var nextscoid = scoes_nav[launch_sco].nextscoid;
|
||||
node.title = scoes_nav[nextscoid].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = nextscoid;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
return scorm_skipnext(node);
|
||||
return scorm_skipnext(node, update_launch_sco);
|
||||
};
|
||||
|
||||
var scorm_skipnext = function(node) {
|
||||
if (node.nextSibling) {
|
||||
var scorm_skipnext = function(node, update_launch_sco) {
|
||||
if (node.nextSibling && typeof scoes_nav[launch_sco].nextsibling != 'undefined') {
|
||||
var nextsibling = scoes_nav[launch_sco].nextsibling;
|
||||
node.nextSibling.title = scoes_nav[nextsibling].url;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = nextsibling;
|
||||
}
|
||||
return node.nextSibling;
|
||||
} else if (node.depth > 0) {
|
||||
return scorm_skipnext(node.parent);
|
||||
} else if (node.depth > 0 && typeof scoes_nav[launch_sco].parentscoid != 'undefined') {
|
||||
var parentscoid = scoes_nav[launch_sco].parentscoid;
|
||||
if (update_launch_sco) {
|
||||
launch_sco = parentscoid;
|
||||
}
|
||||
return scorm_skipnext(node.parent, update_launch_sco);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
mod_scorm_next = scorm_next;
|
||||
mod_scorm_prev = scorm_prev;
|
||||
// Launch prev sco
|
||||
var scorm_launch_prev_sco = function() {
|
||||
var result = null;
|
||||
if (scoes_nav[launch_sco].flow == 1) {
|
||||
var datastring = scoes_nav[launch_sco].url + '&function=scorm_seq_flow&request=backward';
|
||||
result = scorm_ajax_request(M.cfg.wwwroot + '/mod/scorm/datamodels/sequencinghandler.php?', datastring);
|
||||
mod_scorm_seq = encodeURIComponent(result);
|
||||
result = JSON.parse (result);
|
||||
if (typeof result.nextactivity.id != undefined) {
|
||||
var node = scorm_prev(scorm_tree_node.getHighlightedNode())
|
||||
if (node == null) {
|
||||
// Avoid use of TreeView for Navigation
|
||||
node = scorm_tree_node.getHighlightedNode();
|
||||
}
|
||||
node.title = scoes_nav[result.nextactivity.id].url;
|
||||
launch_sco = result.nextactivity.id;
|
||||
scorm_activate_item(node);
|
||||
scorm_fixnav();
|
||||
} else {
|
||||
scorm_activate_item(scorm_prev(scorm_tree_node.getHighlightedNode(), true));
|
||||
}
|
||||
} else {
|
||||
scorm_activate_item(scorm_prev(scorm_tree_node.getHighlightedNode(), true));
|
||||
}
|
||||
};
|
||||
|
||||
// Launch next sco
|
||||
var scorm_launch_next_sco = function () {
|
||||
var result = null;
|
||||
if (scoes_nav[launch_sco].flow == 1) {
|
||||
var datastring = scoes_nav[launch_sco].url + '&function=scorm_seq_flow&request=forward';
|
||||
result = scorm_ajax_request(M.cfg.wwwroot + '/mod/scorm/datamodels/sequencinghandler.php?', datastring);
|
||||
mod_scorm_seq = encodeURIComponent(result);
|
||||
result = JSON.parse (result);
|
||||
if (typeof result.nextactivity.id != undefined) {
|
||||
var node = scorm_next(scorm_tree_node.getHighlightedNode())
|
||||
if (node == null) {
|
||||
// Avoid use of TreeView for Navigation
|
||||
node = scorm_tree_node.getHighlightedNode();
|
||||
}
|
||||
node.title = scoes_nav[result.nextactivity.id].url;
|
||||
launch_sco = result.nextactivity.id;
|
||||
scorm_activate_item(node);
|
||||
scorm_fixnav();
|
||||
} else {
|
||||
scorm_activate_item(scorm_next(scorm_tree_node.getHighlightedNode(), true));
|
||||
}
|
||||
} else {
|
||||
scorm_activate_item(scorm_next(scorm_tree_node.getHighlightedNode(), true));
|
||||
}
|
||||
};
|
||||
|
||||
mod_scorm_launch_prev_sco = scorm_launch_prev_sco;
|
||||
mod_scorm_launch_next_sco = scorm_launch_next_sco;
|
||||
|
||||
// layout
|
||||
Y.YUI2.widget.LayoutUnit.prototype.STR_COLLAPSE = M.str.moodle.hide;
|
||||
@ -403,36 +508,26 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
scorm_buttons[3] = new Y.YUI2.widget.Button('nav_next');
|
||||
scorm_buttons[4] = new Y.YUI2.widget.Button('nav_skipnext');
|
||||
scorm_buttons[0].on('click', function(ev) {
|
||||
scorm_activate_item(scorm_skipprev(scorm_tree_node.getHighlightedNode()));
|
||||
scorm_activate_item(scorm_skipprev(scorm_tree_node.getHighlightedNode(), true));
|
||||
});
|
||||
scorm_buttons[1].on('click', function(ev) {
|
||||
scorm_activate_item(scorm_prev(scorm_tree_node.getHighlightedNode()));
|
||||
scorm_launch_prev_sco();
|
||||
});
|
||||
scorm_buttons[2].on('click', function(ev) {
|
||||
scorm_activate_item(scorm_up(scorm_tree_node.getHighlightedNode()));
|
||||
scorm_activate_item(scorm_up(scorm_tree_node.getHighlightedNode(), true));
|
||||
});
|
||||
scorm_buttons[3].on('click', function(ev) {
|
||||
scorm_activate_item(scorm_next(scorm_tree_node.getHighlightedNode()));
|
||||
scorm_launch_next_sco();
|
||||
});
|
||||
scorm_buttons[4].on('click', function(ev) {
|
||||
scorm_activate_item(scorm_skipnext(scorm_tree_node.getHighlightedNode()));
|
||||
scorm_activate_item(scorm_skipnext(scorm_tree_node.getHighlightedNode(), true));
|
||||
});
|
||||
scorm_nav_panel.render();
|
||||
}
|
||||
|
||||
// finally activate the chosen item
|
||||
var scorm_first_url = tree.getRoot().children[0];
|
||||
var nxt = false;
|
||||
while (nxt = scorm_next(nxt)) {
|
||||
if (nxt.title) {
|
||||
expression = new RegExp('^.*?scoid=' + launch_sco + '.*?$');
|
||||
matches = nxt.title.match(expression);
|
||||
if (matches != null) {
|
||||
scorm_first_url = nxt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var scorm_first_url = tree.getRoot().children[0];
|
||||
scorm_first_url.title = scoes_nav[launch_sco].url;
|
||||
scorm_activate_item(scorm_first_url);
|
||||
|
||||
// resizing
|
||||
@ -443,31 +538,4 @@ M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launc
|
||||
scorm_resize_layout(true);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function scorm_get_prev() {
|
||||
YUI.use('yui2-treeview', function(Y) {
|
||||
scorm_tree_node = Y.YUI2.widget.TreeView.getTree('scorm_tree');
|
||||
if (scorm_tree_node) {
|
||||
var hnode = scorm_tree_node.getHighlightedNode();
|
||||
var prev = mod_scorm_prev(hnode);
|
||||
if (prev) {
|
||||
mod_scorm_activate_item(prev);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scorm_get_next() {
|
||||
YUI.use('yui2-treeview', function(Y) {
|
||||
scorm_tree_node = Y.YUI2.widget.TreeView.getTree('scorm_tree');
|
||||
if (scorm_tree_node) {
|
||||
var hnode = scorm_tree_node.getHighlightedNode();
|
||||
var next = mod_scorm_next(hnode);
|
||||
if (next) {
|
||||
mod_scorm_activate_item(next);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@ -269,12 +269,14 @@ if ($result->prerequisites) {
|
||||
?>
|
||||
</div> <!-- SCORM page -->
|
||||
<?php
|
||||
$scoes = scorm_get_toc_object($USER, $scorm, "", $sco->id, $mode, $attempt);
|
||||
$adlnav = scorm_get_adlnav_json($scoes['scoes']);
|
||||
// NEW IMS TOC
|
||||
if (empty($scorm->popup) || $displaymode == 'popup') {
|
||||
if (!isset($result->toctitle)) {
|
||||
$result->toctitle = get_string('toc', 'scorm');
|
||||
}
|
||||
$PAGE->requires->js_init_call('M.mod_scorm.init', array($scorm->hidenav, $scorm->hidetoc, $result->toctitle, $name, $sco->id));
|
||||
$PAGE->requires->js_init_call('M.mod_scorm.init', array($scorm->hidenav, $scorm->hidetoc, $result->toctitle, $name, $sco->id, $adlnav));
|
||||
}
|
||||
if (!empty($forcejs)) {
|
||||
echo $OUTPUT->box(get_string("forcejavascriptmessage", "scorm"), "generalbox boxaligncenter forcejavascriptmessage");
|
||||
|
Loading…
x
Reference in New Issue
Block a user