﻿$TTFlash met SCORM 1.2-tracking
$DS
Publicatiesjabloon voor ADL/SCORM 1.2-communicatie. Gewijzigd voor ondersteuning van Leerinteracties. Bevat JavaScript om een ADL API 1.2-object te zoeken en te initialiseren en speciale fscommand-opdrachten zodat LMS-functies vanuit Flash kunnen worden aangeroepen.

$DF

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl">
<head>
$CS
<script type="text/javascript" language="JavaScript" name="fsIeVbscript">
<!--
// Hook voor Internet Explorer
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
	document.write('<script language=\"VBScript\"\>\n');
	document.write('On Error Resume Next\n');
	document.write('Sub $TI_FSCommand(ByVal command, ByVal args)\n');
	document.write('	Call $TI_DoFSCommand(command, args)\n');
	document.write('End Sub\n');
	document.write('</script\>\n');
}
//-->
</script>
<title>$TI</title>
</head>
<script type="text/javascript" language="JavaScript" name="cmifrag">
<!--

// FS SCORM - fscommand-adapter voor ADL SCORM 1.2 en Flash MX 2004 Interacties voor leerobjecten
// versie 1.0    08/19/03
// Modified by Andrew Chemey, Macromedia
// Gebaseerd op FS SCORM-adapter, versie 1.2.4:
// \t\tFragments Copyright 2002 Pathlore Software Corporation All rights Reserved
// \t\tFragments Copyright 2002 Macromedia Inc. All rights reserved.
// \t\tFragments Copyright 2003 Click2learn, Inc. All rights reserved.
// \t\tDeveloped by Tom King, Macromedia, Leonard Greenberg, Pathlore, and Claude Ostyn, Click2learn, Inc.
// \t\tIncludes code by Jeff Burton and Andrew Chemey, Macromedia (01/09/02)
// -----------------------------------------------------------------

// Wijzig deze voorinstellingen zoals voor u het meest geschikt is.

var g_bShowApiErrors = false; 	// wijzigen in waar om foutmeldingen weer te geven

var g_bInitializeOnLoad = true; // wijzigen in onwaar om LMS niet te initialiseren wanneer HTML-pagina wordt geladen

// Zet deze tekenreeksen om wanneer g_bShowApiErrors waar is en u deze toepassing moet vertalen.
var g_strAPINotFound = "Management system interface not found.";
var g_strAPITooDeep = "Cannot find API - too deeply nested.";
var g_strAPIInitFailed = "Found API but LMSInitialize failed.";
var g_strAPISetError = "Trying to set value but API not available.";
var g_strFSAPIError = 'LMS API adapter returned error code: "%1"\nWhen FScommand called API.%2\nwith "%3"';
var g_strDisableErrorMsgs = "Select cancel to disable future warnings.";

// Wijzig g_bSetCompletedAutomatically in waar als u wilt dat de status automatisch op voltooid wordt ingesteld wanneer LMSFinish wordt aangeroepen. 
// Normaalgesproken blijft deze markering op onwaar staan wanneer de Flash-film zelf de status op voltooid instelt door een fscommand te verzenden om de status in te stellen op 'voltooid', 'geslaagd' of 'gezakt' (beide impliceren 'voltooid'). "passed" or "failed" (both of which imply "completed")
var g_bSetCompletedAutomatically = false;

// Deze waarde wordt normaalgesproken door het LMS gegeven, maar mocht dit niet het geval zijn, dan is dit de standaardwaarde die moet worden gebruikt om geslaagd/gezakt te bepalen. 
// Stel deze in op nul wanneer de Flash ActionScript-code een eigen methode gebruikt om geslaagd/gezakt te bepalen. Stel deze anders in op een waarde tussen 0 t/m 1 (kan drijvende-kommagetal zijn, zoals 0,75).
var g_SCO_MasteryScore = null; // Toegestane waarden: 0.0..1.0, or null

//==================================================================

// WAARSCHUWING.
// Wijzig niets onder deze regel tenzij u zeker weet wat u doet.
// Deze twee waarden hoeven in principe niet te worden gewijzigd, omdat de voorinstellingen van de Flash-sjabloon hierop zijn gebaseerd.
var g_nSCO_ScoreMin = 0; 		// moet een getal zijn
var g_nSCO_ScoreMax = 100; 		// moet een getal zijn > nSCO_Score_Min

// Conform de SCORM-specificatie zal de door het LMS geboden kennisscore, indien aanwezig, de SCO overschrijven bij het bepalen of de score moet worden geïnterpreteerd wanneer de status geslaagd/gezakt is bepaald.
// De sjabloon probeert de kennisscore te verkrijgen en, wanneer deze beschikbaar is, de status in te stellen op geslaagd of gezakt wanneer de SCO een score verzendt.
// Het LMS stelt de bepaling mogelijk pas vast nadat de SCO is beëindigd.
// De standaardwaarde voor deze markering is waar. Stel deze in op onwaar als u niet wilt voorspellen hoe het LMS de status geslaagd/gezakt zal instellen op basis van de kennisscore (het LMS heeft toch altijd gelijk).
var g_bInterpretMasteryScore = true;

// Dit script implementeert diverse aspecten van de algemene logische werking van een SCO.

/////////// INITIALISATIE VAN API-INTERFACE EN AFVANGFUNCTIES ////////
var g_nFindAPITries = 0;
var g_objAPI = null;
var g_bInitDone = false;
var g_bFinishDone = false;
var	g_bSCOBrowse = false;
var g_dtmInitialized = new Date(); // wordt aangepast na initialisatie
var g_bMasteryScoreInitialized = false;

function AlertUserOfAPIError(strText) {
	if (g_bShowApiErrors) {
		var s = strText + "\n\n" + g_strDisableErrorMsgs;
		if (!confirm(s)){
			g_bShowApiErrors = false
		}
	}
}

function ExpandString(s){
	var re = new RegExp("%","g")
	for (i = arguments.length-1; i > 0; i--){
		s2 = "%" + i;
		if (s.indexOf(s2) > -1){
			re.compile(s2,"g")
			s = s.replace(re, arguments[i]);
		}
	}
	return s
}

function FindAPI(win) {
	while ((win.API == null) && (win.parent != null) && (win.parent != win)) {
		g_nFindAPITries ++;
		if (g_nFindAPITries > 500) {
			AlertUserOfAPIError(g_strAPITooDeep);
			return null;
		}
		win = win.parent;
	}
	return win.API;
}

function APIOK() {
	return ((typeof(g_objAPI)!= "undefined") && (g_objAPI != null))
}

function SCOInitialize() {
	var err = true;
	if (!g_bInitDone) {
		if ((window.parent) && (window.parent != window)){
			g_objAPI = FindAPI(window.parent)
		}
		if ((g_objAPI == null) && (window.opener != null))	{
			g_objAPI = FindAPI(window.opener)
		}
		if (!APIOK()) {
			AlertUserOfAPIError(g_strAPINotFound);
			err = false
		} else {
			err = g_objAPI.LMSInitialize("");
			if (err == "true") {
				g_bSCOBrowse = (g_objAPI.LMSGetValue("cmi.core.lesson_mode") == "browse");						if (!g_bSCOBrowse) {
					if (g_objAPI.LMSGetValue("cmi.core.lesson_status") == "not attempted") {
						err = g_objAPI.LMSSetValue("cmi.core.lesson_status","incomplete")
					}
				}
			} else {
				AlertUserOfAPIError(g_strAPIInitFailed)
			}
		}
		if (typeof(SCOInitData) != "undefined") {
			// De functie SCOInitData kan in een ander script van de SCO worden gedefinieerd.
			SCOInitData()
		}
		g_dtmInitialized = new Date();
	}
	g_bInitDone = true;
	return (err + "") // Stel type geforceerd in op String.
}

function SCOFinish() {
	if ((APIOK()) && (g_bFinishDone == false)) {
		SCOReportSessionTime()
		if (g_bSetCompletedAutomatically){
			SCOSetStatusCompleted();
		}
		if (typeof(SCOSaveData) != "undefined"){
			// De functie SCOSaveData kan in een ander script van de SCO worden gedefinieerd.
			SCOSaveData();
		}
		g_bFinishDone = (g_objAPI.LMSFinish("") == "true");
	}
	return (g_bFinishDone + "" ) // Stel type geforceerd in op String.
}

// Roep deze afvangfuncties aan in plaats van de API-adapter rechtstreeks aan te roepen.
function SCOGetValue(nam)			{return ((APIOK())?g_objAPI.LMSGetValue(nam.toString()):"")}
function SCOCommit()					{return ((APIOK())?g_objAPI.LMSCommit(""):"false")}
function SCOGetLastError()		{return ((APIOK())?g_objAPI.LMSGetLastError():"-1")}
function SCOGetErrorString(n)	{return ((APIOK())?g_objAPI.LMSGetErrorString(n):"No API")}
function SCOGetDiagnostic(p)	{return ((APIOK())?g_objAPI.LMSGetDiagnostic(p):"No API")}

//LMSSetValue is hieronder geïmplementeerd met meer complexe gegevensbeheerlogica.

var g_bMinScoreAcquired = false;
var g_bMaxScoreAcquired = false;

// Speciale logica begint hier
function SCOSetValue(nam,val){
	var err = "";
	if (!APIOK()){
			AlertUserOfAPIError(g_strAPISetError + "\n" + nam + "\n" + val);
			err = "false"
	} else if (nam == "cmi.core.score.raw") err = privReportRawScore(val)
	if (err == ""){
			err = g_objAPI.LMSSetValue(nam,val.toString() + "");
			if (err != "true") return err
	}
	if (nam == "cmi.core.score.min"){
		g_bMinScoreAcquired = true;
		g_nSCO_ScoreMin = val
	}
	else if (nam == "cmi.core.score.max"){
		g_bMaxScoreAcquired = true;
		g_nSCO_ScoreMax = val
	}
	return err
}

function privReportRawScore(nRaw) { // alleen aangeroepen door SCOSetValue
	if (isNaN(nRaw)) return "false";
	if (!g_bMinScoreAcquired){
		if (g_objAPI.LMSSetValue("cmi.core.score.min",g_nSCO_ScoreMin+"")!= "true") return "false"
	}
	if (!g_bMaxScoreAcquired){
		if (g_objAPI.LMSSetValue("cmi.core.score.max",g_nSCO_ScoreMax+"")!= "true") return "false"
	}
	if (g_objAPI.LMSSetValue("cmi.core.score.raw", nRaw)!= "true") return "false";
	g_bMinScoreAcquired = false;
	g_bMaxScoreAcquired = false;
	if (!g_bMasteryScoreInitialized){
		var nMasteryScore = parseInt(SCOGetValue("cmi.student_data.mastery_score"),10);
		if (!isNaN(nMasteryScore)) g_SCO_MasteryScore = nMasteryScore
	}
  	if ((g_bInterpretMasteryScore)&&(!isNaN(g_SCO_MasteryScore))){
    	var stat = (nRaw >= g_SCO_MasteryScore? "passed" : "failed");
    	if (SCOSetValue("cmi.core.lesson_status",stat) != "true") return "false";
  	}
  	return "true"
}

function MillisecondsToCMIDuration(n) {
//Zet duur om van milliseconden in de notatie 0000:00:00.00.
	var hms = "";
	var dtm = new Date();	dtm.setTime(n);
	var h = "000" + Math.floor(n / 3600000);
	var m = "0" + dtm.getMinutes();
	var s = "0" + dtm.getSeconds();
	var cs = "0" + Math.round(dtm.getMilliseconds() / 10);
	hms = h.substr(h.length-4)+":"+m.substr(m.length-2)+":";
	hms += s.substr(s.length-2)+"."+cs.substr(cs.length-2);
	return hms
}

// SCOReportSessionTime wordt automatisch door dit script aangeroepen, maar u kunt deze functie altijd ook via de SCO aanroepen.
function SCOReportSessionTime() {
	var dtm = new Date();
	var n = dtm.getTime() - g_dtmInitialized.getTime();
	return SCOSetValue("cmi.core.session_time",MillisecondsToCMIDuration(n))
}

// Aangezien alleen de ontwerper van een SCO weet wat voltooid inhoudt, kan een ander script van de SCO deze functie aanroepen om de status voltooid in te stellen.
// De functie controleert of de SCO niet in de bladermodus staat en voorkomt het verwijderen van een status 'geslaagd' of 'gezakt' aangezien deze 'voltooid' impliceren.
function SCOSetStatusCompleted(){
	var stat = SCOGetValue("cmi.core.lesson_status");
	if (SCOGetValue("cmi.core.lesson_mode") != "browse"){
		if ((stat!="completed") && (stat != "passed") && (stat != "failed")){
			return SCOSetValue("cmi.core.lesson_status","completed")
		}
	} else return "false"
}

// Objectieve beheerlogica

function SCOSetObjectiveData(id, elem, v) {
	var result = "false";
	var i = SCOGetObjectiveIndex(id);
	if (isNaN(i)) {
		i = parseInt(SCOGetValue("cmi.objectives._count"));
		if (isNaN(i)) i = 0;
		if (SCOSetValue("cmi.objectives." + i + ".id", id) == "true"){
			result = SCOSetValue("cmi.objectives." + i + "." + elem, v)
		}
	} else {
		result = SCOSetValue("cmi.objectives." + i + "." + elem, v);
		if (result != "true") {
			// Mogelijk accepteert dit LMS alleen journaalposten.
			i = parseInt(SCOGetValue("cmi.objectives._count"));
			if (!isNaN(i)) {
				if (SCOSetValue("cmi.objectives." + i + ".id", id) == "true"){
					result = SCOSetValue("cmi.objectives." + i + "." + elem, v)
				}
			}
		}
	}
	return result
}

function SCOGetObjectiveData(id, elem) {
	var i = SCOGetObjectiveIndex(id);
	if (!isNaN(i)) {
		return SCOGetValue("cmi.objectives." + i + "."+elem)
	}
	return ""
}

function SCOGetObjectiveIndex(id){
	var i = -1;
	var nCount = parseInt(SCOGetValue("cmi.objectives._count"));
	if (!isNaN(nCount)) {
		for (i = nCount-1; i >= 0; i--){ //navigeer achterwaarts voor het geval LMS journaliseert
			if (SCOGetValue("cmi.objectives." + i + ".id") == id) {
				return i
			}
		}
	}
	return NaN
}

// Hiermee worden AICC-compatibele tokens of afkortingen omgezet in SCORM-tokens.
function AICCTokenToSCORMToken(strList,strTest){
	var a = strList.split(",");
	var c = strTest.substr(0,1).toLowerCase();
	for (i=0;i<a.length;i++){
			if (c == a[i].substr(0,1)) return a[i]
	}
	return strTest
}

function normalizeStatus(status){
	return AICCTokenToSCORMToken("completed,incomplete,not attempted,failed,passed", status)
}

function normalizeInteractionType(theType){
	return AICCTokenToSCORMToken("true-false,choice,fill-in,matching,performance,sequencing,likert,numeric", theType)
}

function normalizeInteractionResult(result){
	return AICCTokenToSCORMToken("correct,wrong,unanticipated,neutral", result)
}

// Internet Explorer detecteren
var g_bIsInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;

// Handel fscommand-berichten uit een Flash-film af en wijs daarbij zo nodig eventuele AICC Flash-sjabloonopdrachten opnieuw aan SCORM toe
function $TI_DoFSCommand(command, args){

	var $TIObj = g_bIsInternetExplorer ? $TI : document.$TI;

	// no-op wanneer geen SCORM-API beschikbaar is

	var myArgs = new String(args);
	var cmd = new String(command);
	var v = "";
	var err = "true";
	var arg1, arg2, n, s, i;
	var sep = myArgs.indexOf(",");
	if (sep > -1){
		arg1 = myArgs.substr(0, sep); // Naam van gegevenselement dat moet worden verkregen via API
		arg2 = myArgs.substr(sep+1) 	// Naam van Flash-filmvariabele die moet worden ingesteld.
	} else {
		arg1 = myArgs
	}
	if (!APIOK()) return;

	if (cmd.substring(0,3) == "LMS"){
		// Handel fscommand-opdrachten LMSxxx af (compatibel met HTML-sjabloon fsSCORM).
		if ( cmd == "LMSInitialize" ){
			err = (APIOK() + "")
			// De daadwerkelijke LMSInitialize wordt automatisch aangeroepen door de sjabloon
		}	else if ( cmd == "LMSSetValue" ){
			err = SCOSetValue(arg1,arg2)
		} else if ( cmd == "LMSFinish" ){
			err = SCOFinish()
			// Wordt automatisch afgehandeld door de sjabloon, may call it earlier.
		}	else if ( cmd == "LMSCommit" ){
			err = SCOCommit()
		}	else if ( cmd == "LMSFlush" ){
			// no-op
			// LMSFlush is niet gedefinieerd in SCORM en het aanroepen ervan resulteert in een testsuitefout.
		}	else if ((arg2) && (arg2.length > 0)){
			if ( cmd == "LMSGetValue") {
				$TIObj.SetVariable(arg2, SCOGetValue(arg1));
			}	else if ( cmd == "LMSGetLastError") {
				$TIObj.SetVariable(arg2, SCOGetLastError(arg1));
			}	else if ( cmd == "LMSGetErrorString") {
				$TIObj.SetVariable(arg2, SCOGetLastError(arg1));
			}	else if ( cmd == "LMSGetDiagnostic") {
				$TIObj.SetVariable(arg2, SCOGetDiagnostic(arg1));
			}	else {
				// voor onbekende LMSGetxxxx-extensie
				v = eval('g_objAPI.' + cmd + '(\"' + arg1 + '\")');
				$TIObj.SetVariable(arg2,v);
			}
		} else if (cmd.substring(0,3) == "LMSGet") {
			err = "-2: No Flash variable specified"
		}
		// einde afhandeling opdrachten LMSxxx
	} else if ((cmd.substring(0,6) == "MM_cmi")||(cmd.substring(0,6) == "CMISet")) {
		// Handel een fscommand-opdracht van Componenten voor leerobjecten van Macromedia af.
		// Deze gebruiken de AICC HACP-gegevensmodelconventies, gegevens moeten dus opnieuw van AICC aan SCORM worden toegewezen.
		var F_intData = myArgs.split(";");
		if (cmd == "MM_cmiSendInteractionInfo") {
			n = SCOGetValue("cmi.interactions._count");
			s = "cmi.interactions." + n + ".";
			// Vang grove fouten af om mislukken van SCORM-compatibiliteitstest te voorkomen.
			// Wanneer geen id voor deze interactie is opgegeven, kan deze niet worden vastgelegd.
			v = F_intData[2]
			if ((v == null) || (v == "")) err = 201; // Wanneer er geen id is, heeft vastleggen geen zin.
			if (err =="true"){
				err = SCOSetValue(s + "id", v)
			}
			if (err =="true"){
				var re = new RegExp("[{}]","g")
				for (i=1; (i<9) && (err=="true"); i++){
					v = F_intData[i];
					if ((v == null) || (v == "")) continue
					if (i == 1){
						err = SCOSetValue(s + "time", v)
					} else if (i == 3){
						err = SCOSetValue(s + "objectives.0.id", v)
					} else if (i == 4){
						err = SCOSetValue(s + "type", normalizeInteractionType(v))
					} else if (i == 5){
						// verwijder "{" en "}" uit het antwoord
						v = v.replace(re, "");
						err = SCOSetValue(s + "correct_responses.0.pattern", v)
					} else if (i == 6){
						// verwijder "{" en "}" uit het antwoord
						v = v.replace(re, "");
						err = SCOSetValue(s + "student_response", v)
					} else if (i == 7){
						err = SCOSetValue(s + "result", normalizeInteractionResult(v))
					} else if (i == 8){
						err = SCOSetValue(s + "weighting", v)
					} else if (i == 9){
						err = SCOSetValue(s + "latency", v)
					}
				}
			}
		} else if (cmd == "MM_cmiSendObjectiveInfo"){
			err = SCOSetObjectiveData(F_intData[1], ".score.raw", F_intData[2])
			if (err=="true"){
				SCOSetObjectiveData(F_intData[1], ".status", normalizeStatus(F_intData[3]))
			}
		} else if ((cmd=="CMISetScore") ||(cmd=="MM_cmiSendScore")){
			err = SCOSetValue("cmi.core.score.raw", F_intData[0]);
		} else if ((cmd=="CMISetStatus") || (cmd=="MM_cmiSetLessonStatus")){
			err = SCOSetValue("cmi.core.lesson_status", normalizeStatus(F_intData[0]))
		} else if (cmd=="CMISetTime"){
			err = SCOSetValue("cmi.core.session_time", F_intData[0])
		} else if (cmd=="CMISetCompleted"){
			err = SCOSetStatusCompleted()
		} else if (cmd=="CMISetStarted"){
			err = SCOSetValue("cmi.core.lesson_status", "incomplete")
		} else if (cmd=="CMISetPassed"){
			err = SCOSetValue("cmi.core.lesson_status", "passed")
		} else if (cmd=="CMISetFailed"){
			err = SCOSetValue("cmi.core.lesson_status", "failed")
		} else if (cmd=="CMISetData"){
			err = SCOSetValue("cmi.suspend_data", F_intData[0])
		} else if (cmd=="CMISetLocation"){
			err = SCOSetValue("cmi.core.lesson_location", F_intData[0])
		} else if (cmd=="CMISetTimedOut"){
			err = SCOSetValue("cmi.core.exit", "time-out")
		} // Andere fscommand-opdrachten van Componenten voor leerobjecten zijn in deze context no-ops.
	} else {
		if (cmd=="CMIFinish" || cmd=="CMIExitAU"){
			err = SCOFinish()
		} else if (cmd=="CMIInitialize" || cmd=="MM_StartSession"){
			err = SCOInitialize()
		} else {
			// Onbekende opdracht; roept mogelijk een API-uitbreiding aan.
			// Wanneer de opdracht een tweede argument heeft, moet worden otherwise assume it is just a cmd
			if (eval('g_objAPI.' + cmd)) {
				v = eval('g_objAPI.' + cmd + '(\"' + arg1 + '\")');
				if ((arg2) && (arg2.length > 0)){
					$TIObj.SetVariable(arg2,v)
				} else {
					err = v
				}
			} else {
				err = "false"
			}
		}
	}
	// Handle voor einde van opdrachtomzetting en verwerking
	// heeft fouten gedetecteerd, zoals geretourneerde LMS-foutwaarden.
	if ((g_bShowApiErrors) && (err != "true")) {
		AlertUserOfAPIError(ExpandString(g_strFSAPIError, err, cmd, args))
	}
	return err
}
//-->
</script>
<body bgcolor="$BG" onload="SCOInitialize()" onunload="SCOFinish()" onbeforeunload="SCOFinish()">
<script type="text/javascript" language="JavaScript" name="earlyInit">
<!--
// Bepaal of moet worden geprobeerd API te initialiseren voordat de film wordt geladen voor het geval er een ActionScript is dat wordt geactiveerd voordat de rest van de HTML-pagina volledig is geladen.
// U kunt dit configureren door de algemene Booleaanse waarde (g_bInitializeOnLoad) aan het begin van dit bestand in te stellen. De standaardwaarde is WAAR.
if (g_bInitializeOnLoad) {
	SCOInitialize()
}
//-->
</script>
<!--URL's die in de film worden gebruikt-->
$MU
<!--tekst die in de film wordt gebruikt-->
$MT
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=$FV,$JR,$NR,0" id="$TI" width="$WI" height="$HE" align="$HA">
<param name="allowScriptAccess" value="sameDomain" />
$PO
<embed $PEwidth="$WI" height="$HE" name="$TI" align="$HA" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_nl" />
</object>
</body>
</html>
