﻿$TTFlash med SCORM 2004-uppföljning
$DS
Publiceringsmall för SCORM 2004-kommunikation. Mallen har modifierats särskilt för Utbildningsinteraktioner. Innehåller JavaScript för att söka efter och initera ett ADL API 1.2-objekt samt FSCommand-"klister" som gör att LMS-funktioner kan anropas från Flash.

$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="sv" lang="sv">
<head>
$CS
<script type="text/javascript" language="JavaScript" name="fsIeVbscript">
<!--
// Koppling för 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 för ADL SCORM 2004 och Flash MX 2004 Learning Interactions
// version 1.0    12/10/04
// Modified by Andrew Chemey, Macromedia
// Baseras på version 1.2.4 av FS SCORM-adaptern:
// \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)
// -----------------------------------------------------------------

// Ändra dessa förinställda värden så att det passar dina behov.
// Söka efter API-objekt (0 – startar nedifrån; 1 – startar uppifrån)
var g_intAPIOrder = 1;
var g_bShowApiErrors = false; 	// ändra till true för att visa felmeddelanden

var g_bInitializeOnLoad = true; // ändra till false om LMS inte ska initieras när HTML-sidan läses in

// Översätt dessa strängar om g_bShowApiErrors är true och programmet behöver lokaliseras
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.";

// Ändra g_bSetCompletedAutomatically till true om du vill att statusen ska ställas in på completed automatiskt när LMSFinish anropas.
// Den här flaggan förblir normalt false om Flash-filmen själv anger att statusen är completed genom att ett FSCommand-kommando används för att ställa in statusen på "completed", "passed" eller "failed" (båda dessa innebär även "completed"). "passed" or "failed" (both of which imply "completed")"
var g_bSetCompletedAutomatically = false;

// Det här värdet anges normalt av LMS, men om det inte gör det är det här standardvärdet som används för att avgöra om statusen är passed eller failed.
// Ställ in värdet på null om Flash-skriptet har en egen metod som avgör om statusen är passed eller failed. Ange annars ett värde från 0 till 1 (inklusivt, kan vara ett flyttal, till exempel "0.75").
var g_SCO_MasteryScore = null; // tillåtna värden: 0.0..1.0, or null

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

// VARNING!
// Ändra ingenting nedanför den här raden om du inte är säker på att du vet vad du gör.

// Du behöver normalt inte ändra dessa två värden eftersom Flash-mallens förinställda värden baseras på dem.
var g_nSCO_ScoreMin = 0; 		// måste vara ett tal
var g_nSCO_ScoreMax = 100; 		// måste vara ett tal > nSCO_Score_Min

// Enligt SCORM-specifikationen ersätter en eventuell färdighetspoäng från LMS SCO för att avgöra om poängen ska tolkas när statusen (passed eller failed) avgörs.
// Mallen försöker hämta färdighetspoängen. Om den är tillgänglig ställs statusen in på passed eller failed när SCO skickar ett poängvärde.
// LMS kan inte göra bedömningen förrän SCO har avslutats.
// Standardvärdet för den här flaggan är true. Ställ in den på false om du inte vill förutse hur LMS kommer att ställa in statusen (passed eller failed) baserat på färdighetspoängen (LMS är ändå alltid avgörande).
var g_bInterpretMasteryScore = true;

// Skriptet implementerar olika typer av normalt logiskt beteende för en SCO.

/////////// API-GRÄNSSNITTSINITIERING OCH CATCH-FUNKTIONER ////////
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(); // justeras efter initieringen
var g_bMasteryScoreInitialized = false;

var g_varInterval = "";			// global intervall
var g_intIntervalSecs = 3 		// Antal sekunder att vänta på att SCORM API ska läsas in
var g_intPollSecs = 0.25			// Antal sekunder att avfråga för API
var g_intCurrentTime = new Date().getTime();
var g_intAPI = 0;				// Typ av API att börja söka efter; tillåtna värden: 0 – SCORM 2004; 1 – SCORM 1.2 (eller 1.1)
var g_aryAPI = ["1.0", "0.2"]	// Array som lagrar API-versionerna
var g_strAPIVersion = -1;

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)
{
	// Sök i fönsterhierarkin efter ett objekt med namnet "API_1484_11" för SCORM 2004 eller "API" för SORM 1.2 eller tidigare
	// Sök i det aktuella fönstret (win) och sök rekursivt i eventuella underordnade bildrutor
	if(g_intAPI == 0)
	{
		if(win.API_1484_11 != null)
		{
			return win.API_1484_11;
		}
	} else if(g_intAPI == 1 || g_intAPI == "") {
		if (win.API != null)
		{
			g_strAPIVersion = g_aryAPI[g_intAPI];
			return win.API;
		}
	}

	if (win.length > 0)  // kontrollera bildrutor
	{
		for (var i=0;i<win.length;i++)
		{
			var objAPI = findAPI(win.frames[i]);
			if (objAPI != null)
			{
				return objAPI;
			}
		}
	}
	return null;
}


function getAPI(intAPISearchOrder)
{
	// intAPISearchOrder är 0 – starta i det nuvarande fönstret och gå uppåt; 1 – starta i det översta fönstret och gå nedåt.
	var objAPI = null;
	intAPISearchOrder=((typeof(intAPISearchOrder)=='undefined')?0:intAPISearchOrder);
	if(intAPISearchOrder==0)
	{
		// börja i det nuvarande fönstret och gå uppåt genom överordnade fönster/bildrutor
		objAPI = findAPI(window);
		if((objAPI==null) && (window.opener != null) && (typeof(window.opener) != "undefined"))
		{
			objAPI = findAPI(window.opener);
		} else if((objAPI==null) && (window.parent != null) && (typeof(window.parent) != "undefined")) {
			objAPI = findAPI(window.parent);
		}
		if((objAPI==null) && (g_intAPI < (g_aryAPI.length-1)))
		{
			g_intAPI++;
			objAPI = getAPI(intAPISearchOrder);
		}
	} else {
		// börja i det översta fönstret och gå nedåt genom underordnade bildrutor
		objAPI = findAPI(this.top);

		if (objAPI == null)
		{
			// API hittades inte i det nuvarande fönstrets hierarki. Om det nuvarande fönstret har ett öppnarfönster (startades från ett annat fönster), söker du i öppnarfönstrets hierarki.
			objTopWindow=window.top;

			objTopWindow = objTopWindow.opener;

			while (objTopWindow && !objAPI)
			{
				//kontrollera öppnarfönstret
				objAPI = findAPI(objTopWindow.top);
				if (objAPI==null) objTopWindow = objTopWindow.opener;
			}
			if(objAPI==null && g_intAPI < (g_aryAPI.length-1))
			{
				g_intAPI++;
				objAPI = getAPI(intAPISearchOrder);
			}
		}
	}
	if(objAPI==null)
	{
		// det går inte att hitta API
	} else if(objAPI != null && g_strAPIVersion == -1) {
		g_strAPIVersion = objAPI.version;
	}

	return objAPI;
}

function waitForAPI()
{
	if(new Date().getTime() > (g_intCurrentTime + g_intIntervalSecs*1000) || APIOK())
	{
		// timeout eller API hittades
		clearInterval(g_varInterval);
		if(!APIOK())
		{
			g_objAPI = null;
		} else {
			if (g_bInitializeOnLoad) {
				SCOInitialize()
			}
		}
	} else {
		g_objAPI = getAPI(g_intAPIOrder);
	}
}

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

function SCOInitialize() {
	var err = true;
	if (!g_bInitDone) {
		if (!APIOK()) {
			AlertUserOfAPIError(g_strAPINotFound);
			err = false
		} else {
			err = g_objAPI.Initialize("");
			if (err == "true") {
				g_bSCOBrowse = (g_objAPI.GetValue("cmi.mode") == "browse");
				if (!g_bSCOBrowse) {
					if (g_objAPI.GetValue("cmi.completion_status") == "not attempted") {
						err = g_objAPI.SetValue("cmi.completion_status","incomplete")
					}
				}
			} else {
				AlertUserOfAPIError(g_strAPIInitFailed)
			}
		}
		if (typeof(SCOInitData) != "undefined") {
			// Funktionen SCOInitData kan definieras i ett annat skript i SCO
			SCOInitData()
		}
		g_dtmInitialized = new Date();
	}
	g_bInitDone = true;
	return (err + "") // Tvinga typ för sträng
}

function SCOFinish() {
	if ((APIOK()) && (g_bFinishDone == false)) {
		SCOReportSessionTime()
		if (g_bSetCompletedAutomatically){
			SCOSetStatusCompleted();
		}
		if (typeof(SCOSaveData) != "undefined"){
			// Funktionen SCOSaveData kan definieras i ett annat skript i SCO
			SCOSaveData();
		}
		g_bFinishDone = (g_objAPI.Terminate("") == "true");
	}
	return (g_bFinishDone + "" ) // Tvinga typ för sträng
}

// Anropa dessa catch-funktioner i stället för att försöka anropa API-adaptern direkt
function SCOGetValue(nam)			{return ((APIOK())?g_objAPI.GetValue(nam.toString()):"")}
function SCOCommit()					{return ((APIOK())?g_objAPI.Commit(""):"false")}
function SCOGetLastError()		{return ((APIOK())?g_objAPI.GetLastError():"-1")}
function SCOGetErrorString(n)	{return ((APIOK())?g_objAPI.GetErrorString(n):"No API")}
function SCOGetDiagnostic(p)	{return ((APIOK())?g_objAPI.GetDiagnostic(p):"No API")}

//LMSSetValue implementeras med mer komplicerad datahanteringslogik nedan

var g_bMinScoreAcquired = false;
var g_bMaxScoreAcquired = false;

// Speciallogik börjar här
function SCOSetValue(nam,val){
	var err = "";
	if (!APIOK()){
			AlertUserOfAPIError(g_strAPISetError + "\n" + nam + "\n" + val);
			err = "false"
	} else if (nam == "cmi.score.raw") err = privReportRawScore(val)
	if (err == ""){
			err = g_objAPI.SetValue(nam,val.toString() + "");
			if (err != "true") return err
	}
	if (nam == "cmi.score.min"){
		g_bMinScoreAcquired = true;
		g_nSCO_ScoreMin = val
	}
	else if (nam == "cmi.score.max"){
		g_bMaxScoreAcquired = true;
		g_nSCO_ScoreMax = val
	}
	return err
}

function privReportRawScore(nRaw) { // anropas bara av SCOSetValue
	if (isNaN(nRaw)) return "false";
	if (!g_bMinScoreAcquired){
		if (g_objAPI.SetValue("cmi.score.min",g_nSCO_ScoreMin+"")!= "true") return "false"
	}
	if (!g_bMaxScoreAcquired){
		if (g_objAPI.SetValue("cmi.score.max",g_nSCO_ScoreMax+"")!= "true") return "false"
	}
	if (g_objAPI.SetValue("cmi.score.raw", nRaw)!= "true") return "false";
	g_bMinScoreAcquired = false;
	g_bMaxScoreAcquired = false;
	if (!g_bMasteryScoreInitialized){
		var nTemp = SCOGetValue("cmi.scaled_passing_score");
		nTemp = (nTemp <= 0?0:nTemp * 100);
		var nMasteryScore = parseInt(nTemp,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.success_status",stat) != "true") return "false";
  	}
  	return "true"
}

function MillisecondsToCMIDuration(n) {
//Konvertera varaktighet från millisekunder till formatet 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 = "PT" + h.substr(h.length-4)+"H"+m.substr(m.length-2)+"M";
	hms += s.substr(s.length-2)+"S";
	return hms
}

// SCOReportSessionTime anropas automatiskt av det här skriptet, men du kan dessutom anropa det från SCO när som helst
function SCOReportSessionTime() {
	var dtm = new Date();
	var n = dtm.getTime() - g_dtmInitialized.getTime();
	return SCOSetValue("cmi.session_time",MillisecondsToCMIDuration(n))
}

// Eftersom bara den som konstruerat en SCO vet vad "completed" innebär, kan ett annat skript i SCO:n anropa funktionen för att ställa in statusen på "completed".
// Funktionen kontrollerar att SCO inte är i bläddringsläge utan att ange statusen "passed" eller "failed" eftersom de även innebär "completed".
function SCOSetStatusCompleted(){
	var stat = SCOGetValue("cmi.completion_status");
	if (SCOGetValue("cmi.lesson_mode") != "browse"){
		if ((stat!="completed") && (stat != "passed") && (stat != "failed")){
			return SCOSetValue("cmi.completion_status","completed")
		}
	} else return "false"
}

// Objektiv hanteringslogik

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") {
			// Denna LMS kanske bara accepterar journalposter
			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--){ //gå bakåt om LMS för journal
			if (SCOGetValue("cmi.objectives." + i + ".id") == id) {
				return i
			}
		}
	}
	return NaN
}

// Konverterar AICC-kompatibla token eller förkortningar till SCORM-token
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){
	var strInteractionResult = AICCTokenToSCORMToken("correct,wrong,unanticipated,neutral", result)
	strInteractionResult = (strInteractionResult=="wrong"?"incorrect":strInteractionResult);
	return strInteractionResult;
}

function checkInteractionResponse(response_str)
{
	var result_str = "";
	for(var char_int=0;char_int<response_str.length;char_int++)
	{
		if(response_str.substr(char_int,1) == "." || response_str.substr(char_int,1) == ",")
		{
			if(response_str.substr(char_int - 1,1) != "[" && response_str.substr(char_int + 1,1) != "]")
			{
				result_str += "[" + response_str.substr(char_int,1) + "]";
			} else {
				result_str += response_str.substr(char_int,1);
			}
		} else {
			result_str += response_str.substr(char_int,1);
		}
	}
	result_str = (result_str==""?"0":result_str);
	return result_str;
}

function formatTimestamp(time_var)
{
	return formatDate() + "T" + formatTime(time_var, undefined, undefined, 2);
}


// ******************************************************************
// *
// *     Metod:           formatTime
// *     Beskrivning:      Formaterar sekunder (skickas som parameter) till PTxHyMzS
// *     Returnerar:       Sträng (tiden formateras till HHHH:MM:SS
// *
// ******************************************************************
function formatTime(time_var, minutes_str, seconds_str, typeFormat_int)
{
	var days_str, hours_str, formattedTime_str;
	days_str = "0";
	if(time_var == undefined)
	{
		// Skapa tid baserat på dagens aktuella tid
		var time_obj = new Date();
		hours_str = time_obj.getHours();
		minutes_str = time_obj.getMinutes();
		seconds_str = time_obj.getSeconds();
	} else if(typeof(time_var) == "string" && time_var.indexOf(":") > -1) {
		var time_obj = time_var.split(":");
		hours_str = time_obj[0];
		minutes_str = time_obj[1];
		seconds_str = time_obj[2];
	} else {
		days_str    = "0";
		seconds_str = "0";
		minutes_str = "0";
		hours_str     = "0";

		seconds_str = Math.round(time_var);
		if(seconds_str > 59)
		{
			minutes_str = Math.round(seconds_str / 60);
			seconds_str = seconds_str - (minutes_str * 60);
		}
		if(minutes_str > 59)
		{
			hours_str = Math.round(minutes_str / 60);
			minutes_str = minutes_str - (hours_str * 60);
		}
		if(hours_str > 23)
		{
			days_str = Math.round(hours_str / 24);
			hours_str = hours_str - (days_str * 24);
		}
	}

	if(typeFormat_int == undefined || typeFormat_int == 1)
	{
		formattedTime_str = "P";

		if(days_str != "0")
		{
			formattedTime_str += days_str + "D";
		}
		formattedTime_str += "T" + hours_str + "H" + minutes_str + "M" + seconds_str + "S";
	} else {
		formattedTime_str = formatNum(hours_str, 2) + ":" + formatNum(minutes_str, 2) + ":" + formatNum(seconds_str, 2);
	}
	return formattedTime_str;
}

// ******************************************************************
// *
// *     Metod:           formatDate
// *     Beskrivning:      Formaterar sekunder eller "MM/DD/ÅÅÅÅ"
// *     Returns:          Sträng (datum formateras till "ÅÅÅÅ-MM-DD")
// *
// ******************************************************************
function formatDate(date_var, day_str, year_str)
{
	if (date_var == undefined) {
		// Skapa datum baserat på dagens datum
		var date_obj = new Date();
		date_var = formatNum((date_obj.getMonth()+1), 2);
		day_str  = formatNum((date_obj.getDate()), 2);
		year_str = (date_obj.getFullYear());
	} else if(typeof(date_var) == "string" && date_var.indexOf("/") > -1) {
		// Konvertera från MM/DD/ÅÅÅÅ
		var date_obj = date_var.split("/");
		date_var = formatNum(date_obj[0], 2);
		day_str  = formatNum(date_obj[1], 2);
		year_str = formatNum(date_obj[2], 4);
	}
	var formattedDate_str = (year_str + "-" + date_var + "-" + day_str);
	return formattedDate_str;
}

// ******************************************************************
// *
// *     Metod:           formatNum
// *    Beskrivning:   Konverterar talet som skickas till funktionen till ett utfyllt värde, vanligen tvåsiffrigt eller fyrsiffrigt (till exempel 2 till 02 eller 2 till 0002)
// *    Returns:       Sträng (utfyllt med antal skickade nollor
// *
// ******************************************************************
function formatNum (initialValue_var, numToPad_int)
{
	var paddedValue_str = "";                         // Sträng; innehåller värdet med utfyllningsnollor
	var i = 0;                                     // Heltal; variabel som används för slingor
	var initialValue_str = initialValue_var.toString();    // Sträng; konverterar parametern "initializeValue_var" explicit till en sträng

	if (initialValue_str.length > numToPad_int)
	{
		// fel – startvärdets längd överskrider redan antalet som talet ska fyllas ut till. Returnerar initialValue_var utan utfyllning
	} else {
		for (var i = 1; i <= (numToPad_int - initialValue_str.length); i++)
		{
			paddedValue_str = paddedValue_str + "0";
		}
	}
	paddedValue_str = paddedValue_str + initialValue_var;
	return paddedValue_str;
}

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

// Hantera fscommand-meddelanden från en Flash-film. Alla AICC Flash-mallkommandon mappas om till SCORM om det behövs
function $TI_DoFSCommand(command, args){

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

	// fungerar inte om det inte finns någon SCORM API

	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); // Namn på dataelement som ska hämtas från API
		arg2 = myArgs.substr(sep+1) 	// Namnet på Flash-filmvariabeln som ska ställas in
	} else {
		arg1 = myArgs
	}
	if (!APIOK()) return;

	if (cmd.substring(0,3) == "LMS"){
		// Hantera "LMSxxx"-FScommands (kompatibla med HTML-mallen fsSCORM)
		if ( cmd == "LMSInitialize" ){
			err = (APIOK() + "")
			// Den faktiska LMSInitialize anropas automatiskt av mallen
		}	else if ( cmd == "LMSSetValue" ){
			alert('LMSSetValue: \r\rArg1: ' + arg1 + '\rArg2: ' + arg2);
			err = SCOSetValue(arg1,arg2)
		} else if ( cmd == "LMSFinish" ){
			err = SCOFinish()
			// Hanteras automatiskt av mallen, men kan anropas tidigare av filmen.
		}	else if ( cmd == "LMSCommit" ){
			err = SCOCommit()
		}	else if ( cmd == "LMSFlush" ){
			// no-op
			// LMSFlush för felfunktion är inte definierad i SCORM och om den anropas uppstår fel i testningen
		}	else if ((arg2) && (arg2.length > 0)){
			if ( cmd == "LMSGetValue") {
				alert('LMSSetValue: \r\rArg1: ' + arg1 + '\rArg2: ' + arg2);
				$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 {
				// för okänt LMSGetxxxx-tillägg
				v = eval('g_objAPI.' + cmd + '(\"' + arg1 + '\")');
				$TIObj.SetVariable(arg2,v);
			}
		} else if (cmd.substring(0,3) == "LMSGet") {
			err = "-2: No Flash variable specified"
		}
		// slut på hantering av "LMSxxx"-kommandon
	} else if ((cmd.substring(0,6) == "MM_cmi")||(cmd.substring(0,6) == "CMISet")) {
		// Hantera FScommands för Macromedia Learning Components.
		// För dessa används AICC HACP-datamodellkonventioner. Mappa därför om data från AICC till SCORM när det behövs.
		var F_intData = myArgs.split(";");
		if (cmd == "MM_cmiSendInteractionInfo") {
			n = SCOGetValue("cmi.interactions._count");
			s = "cmi.interactions." + n + ".";
			// Hantera bruttofel så att testfel för SCORM-kompatibilitet kan undvikas
			// Om inget ID anges för den här interaktionen kan den inte registreras
			v = F_intData[2]
			if ((v == null) || (v == "")) err = 201; // Det är meningslöst att registrera utan ID
			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 + "timestamp", formatTimestamp(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){
						// strip out "{" and "}" from response
						v = v.replace(re, "");
						err = SCOSetValue(s + "correct_responses.0.pattern", checkInteractionResponse(v))
					} else if (i == 6){
						// strip out "{" and "}" from response
						v = v.replace(re, "");
						err = SCOSetValue(s + "learner_response", checkInteractionResponse(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.score.raw", F_intData[0]);
		} else if ((cmd=="CMISetStatus") || (cmd=="MM_cmiSetLessonStatus")){
			var strTempStatus = normalizeStatus(F_intData[0]);
			if (strTempStatus == "passed" || strTempStatus == "failed")
			{
				err = SCOSetValue("cmi.success_status", normalizeStatus(F_intData[0]))
			} else {
				err = SCOSetValue("cmi.completion_status", normalizeStatus(F_intData[0]))
			}
		} else if (cmd=="CMISetTime"){
			err = SCOSetValue("cmi.session_time", formatTime(F_intData[0]))
		} else if (cmd=="CMISetCompleted"){
			err = SCOSetStatusCompleted()
		} else if (cmd=="CMISetStarted"){
			err = SCOSetValue("cmi.completion_status", "incomplete")
		} else if (cmd=="CMISetPassed"){
			SCOSetValue("cmi.completion_status", "completed");
			err = SCOSetValue("cmi.success_status", "passed")
		} else if (cmd=="CMISetFailed"){
			SCOSetValue("cmi.completion_status", "completed");
			err = SCOSetValue("cmi.success_status", "failed")
		} else if (cmd=="CMISetData"){
			err = SCOSetValue("cmi.suspend_data", F_intData[0])
		} else if (cmd=="CMISetLocation"){
			err = SCOSetValue("cmi.location", F_intData[0])
		} else if (cmd=="CMISetTimedOut"){
			err = SCOSetValue("cmi.exit", "time-out")
		} // Inga andra FScommands för Learning Component fungerar i kontexten
	} else {
		if (cmd=="CMIFinish" || cmd=="CMIExitAU"){
			err = SCOFinish()
		} else if (cmd=="CMIInitialize" || cmd=="MM_StartSession"){
			err = SCOInitialize()
		} else {
			// Okänt kommando. Kan anropa ett API-tillägg
			// Anta att ett värde förväntas om kommandot har ett andra argument. Anta annars att det bara är ett kommando
			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"
			}
		}
	}
	// Slut på kommandoöversättning och hantering av
	// identifierade fel. Sådana LMS-fel returneras.
	if ((g_bShowApiErrors) && (err != "true")) {
		AlertUserOfAPIError(ExpandString(g_strFSAPIError, err, cmd, args))
	}
	return err
}
//-->
</script>
<body bgcolor="$BG" onunload="SCOFinish()" onbeforeunload="SCOFinish()">
<script type="text/javascript" language="JavaScript" name="earlyInit">
<!--
// Avgör om försök att initiera API ska göras innan en film läses in om det finns en ActionScript som aktiveras innan resten av HTML-sidan har lästs in.
// Detta kan konfigureras genom att det globala booleska värdet (g_bInitializeOnLoad) ställs in i början av filen. Standardvärdet är TRUE.

// Leta efter SCORM API
g_varInterval = setInterval('waitForAPI()', (g_intPollSecs * 1000));

//-->
</script>
<!--URL:er som används i filmen-->
$MU
<!--text som används i filmen-->
$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_se" />
</object>
</body>
</html>
