﻿//**********LMSApi javascript object ******************
var oXmlRetval = null;
var xmlHttp;
var _jsObjHandle;

   function LMSApi(){
   
		this.Initialize = _initialize;
		this.Terminate = _terminate;
		this.GetValue = _getValue;
		this.SetValue = _setValue;
		this.Commit = _commit;
		this.GetLastError = _getLastError;
		this.GetErrorString = _getErrorString;
		this.GetDiagnostic = _getDiagnostic;
		this.setIsBrowserNetscape = _setIsBrowserNetscape;
		this.setTestIDInfo = _setTestIDInfo;
		this.startTest = _startTest;
		this.endTest = _endTest;
		this.closeWindow = _closeWindow;
		this.abortSCOTest = _abortSCOTest;
		this.handleCollections = _handleCollections;
		this.writeXmlData = _writeXmlData;
		this.sendingCmiData = false;
		
		this.SessionID = null;
		this.isTerminated = false;
		
		this.cmi = {_version:{type:"string",RW:"R"},comments_from_learner:{methods:"_children,_count",collection:{comment:{type:"CData",RW:"RW"},location:{type:"CData",RW:"RW"},timestamp:{type:null,RW:"RW"}}},
			comments_from_lms:{methods:"_children,_count",collection:{comment:{type:"CData",RW:"R"},location:{type:"CData",RW:"R"},timestamp:{type:null,RW:"R"}}},
			completion_status:{type:null,RW:"RW"},completion_threshold:{type:null,RW:"R"},credit:{type:null,RW:"R"},entry:{type:null,RW:"R"},exit:{type:null,RW:"W"},interactions:{methods:"_children,_count",collection:{id:{type:"longID",RW:"RW"},type:{type:null,RW:"RW"},
			objectives:{methods:"_count",collection:{id:{type:null,RW:"RW"}}},timestamp:{type:null,RW:"RW"},
			correct_responses:{methods:"_count",collection:{pattern:{type:null,RW:"RW"}}},weighting:{type:null,RW:"RW"},learner_response:{type:null,RW:"RW"},
			result:{type:null,RW:"RW"},latency:{type:null,RW:"RW"},description:{type:null,RW:"RW"}}},launch_data:{type:"CData",RW:"R"},learner_id:{type:null,RW:"R"},learner_name:{type:null,RW:"R"},
			learner_preference:{methods:"_children",audio_level:{type:null,RW:"RW"},language:{type:null,RW:"RW"},delivery_speed:{type:null,RW:"RW"},audio_captioning:{type:null,RW:"RW"}},
			location:{type:"CData",RW:"RW"},max_time_allowed:{type:null,RW:"R"},mode:{type:null,RW:"R"},objectives:{methods:"_children,_count",collection:{id:{type:null,RW:"RW"},
			score:{methods:"_children",scaled:{type:null,RW:"RW"},raw:{type:null,RW:"RW"},min:{type:null,RW:"RW"},max:{type:null,RW:"RW"}},
			success_status:{type:null,RW:"RW"},completion_status:{type:null,RW:"RW"},progress_measure:{type:null,RW:"RW"},description:{type:"CData",RW:"RW"}}},
			progress_measure:{type:null,RW:"RW"},scaled_passing_score:{type:null,RW:"R"},score:{methods:"_children",scaled:{type:null,RW:"RW"},raw:{type:null,RW:"RW"},max:{type:null,RW:"RW"},min:{type:null,RW:"RW"}},
			session_time:{type:null,RW:"W"},success_status:{type:null,RW:"RW"},suspend_data:{type:"CData",RW:"RW"},time_limit_action:{type:null,RW:"R"},total_time:{type:null,RW:"R"}}

		this._cmi = {_version:"1.0"};
		
		this.arrErrorCodes = {"101":{name:"General Exception",diag:"Der er opstået en generel fejl."},"102":{name:"General Initialization Failure"},"103":{name:"Already Initialized"},"104":{name:"Content Instance Terminated"},
			"111":{name:"General Termination Failure"},"112":{name:"Termination Before Initialization"},"113":{name:"Termination After Termination"},"122":{name:"Retrieve Data Before Initialization"},
			"123":{name:"Retrieve Data After Termination"},"132":{name:"Store Data Before Initialization"},"133":{name:"Store Data After Termination"},"142":{name:"Commit Before Initialization"},
			"143":{name:"Commit After Termination"},"201":{name:"General Argument Error"},"301":{name:"General Get Failure"},"351":{name:"General Set Failure"},"391":{name:"General Commit Failure"},
			"401":{name:"Undefined Data Model Element"},"402":{name:"Unimplemented Data Model Element"},"403":{name:"Data Model Element Value Not Initialized"},"404":{name:"Data Model Element Is Read Only"},
			"405":{name:"Data Model Element Is Write Only"},"406":{name:"Data Model Element Type Mismatch"},"407":{name:"Data Model Element Value Out Of Range"},"408":{name:"Data Model Dependency Not Established"}}
		
		this.LastError = "0";
		this.initialized = false;
		this.scoUserID; 
		this.startTime; 
		this.scoLocation;
   
   function _initialize(iInParameter, boolean){
        this.initialized = true;
		return true;
   }
   
	function _terminate()	 
	{
        if(this.initialized==false)
        {
            //Not Initialized
            this.LastError = "112";
        }
        else if(this.isTerminated==true)
        {
            //Allready terminated
            this.LastError = "113";
        }
        else
        {
            this.LastError = "0";
            this.isTerminated = true;
        }
        jsObjHandle = this;
        this.closeWindow();
        return (this.LastError == "0");
	}
	
	var i = 0;
	
	function _closeWindow()
	{
	    if(_jsObjHandle.sendingCmiData == true)
        {
            window.setTimeout("_jsObjHandle.closeWindow()", 100)
        }
        else
        {   
            if(scoWin)
            {
                scoWin.close();
            }
        }
        
	}
	
	function _getValue(name){    
	    //Todo need to unescape the value returned by this function
	    //Tomas on Dec 7 2007 to fix a problem caused by correct_responses containing the value <else>
	    //this was added to the _setValue function and we need a correspondinng Unescape
	    //value = escape(value)
	    
	    if(name == "cmi.success_status")
	    {
	        var scaled_passing_score = this._cmi.scaled_passing_score;
	        var scaled_score = this._cmi.score.scaled;
	        var retVal;
	        
	        if(scaled_passing_score && scaled_score)
	        {
	            retVal = (scaled_score>=scaled_passing_score) ? "passed" : "failed";
	        }
	        else
	        {
	            var succes_status = this._cmi.succes_status;
	            retVal = succes_status ? succes_status : "unknown";
	        }
	        this.LastError == 0;
	        return retVal;
	    }
	    else if(name == "cmi.completion_status")
	    {
	        var completion_threshold = this._cmi.completion_threshold;
	        var progress_measure = this._cmi.progress_measure;
	        var retVal;
	        
	        if(completion_threshold && progress_measure)
	        {
	            retVal = (progress_measure>=completion_threshold) ? "completed" : "incomplete";
	        }
	        else
	        {
	            var completion_status = this._cmi.completion_status;
	            retVal = completion_status ? completion_status : "unknown";
	        }
	        this.LastError == 0;	 
	        return retVal;       
	    }
	    else
	    {
		    var oFunction = null;
		    var strFunction = ""
		    if(name.indexOf("_children")>-1){
			    name = name.substring(0,name.indexOf("_children")-1);
			    oFunction = _children;
			    strFunction = "_children";
		    }
		    else if(name.indexOf("_count")>-1){
			    name = name.substring(0,name.indexOf("_count")-1);
			    oFunction = _count;
			    strFunction = "_count";
		    }
		    //if index is in string - replace .n with [n] in order to get the indexed object
		    var arrName = name.split(".");
		    var arrNewName = new Array;
		    for (var i = 0; i < arrName.length; i++) {
			    if (isNaN(arrName[i])==false){
				    arrNewName[i] = "collection";
				    arrName[i] = "["+arrName[i]+"]";
			    }
			    else{
				    arrNewName[i] = arrName[i]
			    }
		    }
		    var testName = arrNewName.join(".")
		    try{
			    eval("var oTestObj = this."+ testName);
		    }
		    catch(ex){
			    this.LastError = "401";
			    return ""
		    }
    		
		    if(oTestObj){
			    if(oFunction!=null){//_count and _children methods
				    //alert("if function is _children don't need to check if it's in _cmi")
				    if(oTestObj.methods.indexOf(strFunction)==-1){//the called method is not in collections methods property in Template object
					    this.LastError = "301";
					    return ""
				    }
				    else{
					    if(strFunction=="_children"){
						    this.LastError = "0";
						    return oFunction(oTestObj);
					    }
				    }
			    }
			    name = arrName.join(".");
			    var r,re;
			    re = /\.\[/g
			    r = name.replace(re,"[")
			    name = r;
			    var newName = "this._cmi." + name.substring(name.indexOf(".")+1,name.length);
			    try{
				    eval("var oTestNewObj = " + newName);
			    }
			    catch(ex){
				    this.LastError = "403";
				    return ""
			    }
			    if(oFunction!=null){
				    if(oTestNewObj==undefined){
					    this.LastError = "0";
					    return 0;
				    }
				    else{
					    this.LastError = "0";
					    return oFunction(oTestNewObj);
				    }
			    }
			    else if(oTestObj.collection){
				    this.LastError = "301";
				    return "";
			    }
			    else{
				    if(oTestObj.RW.indexOf("R")>-1){
				        this.LastError = "0"
				        if (oTestNewObj == undefined) {
				            return "";
				        }
				        else {
				            return unescapeFromLms(oTestNewObj);
				        }
				    }
				    else{
					    this.LastError ="405";
					    return "";
				    }
			    }
		    }
		    else{ //elementet doesn't exist in datamodel
			    this.LastError = "401";
			    return "";		
		    }
		}
	}
	
	function unescapeFromLms(strInput)
	{
	    var regExp = /\\'/g;
	    var retVal = unescape(strInput);
	    retVal = retVal.replace(regExp, "'");
	    return retVal;
	}
	
	function escapeForLms(strInput)
	{
		var regExp = /'/g;
	    var retVal = escape(strInput);
	    retVal = retVal.replace(regExp, "\'");
	    return retVal;
	}
	
	function _setValue(name, value){
	    //added by Tomas on Dec 7 2007 to fix a problem caused by correct_responses containing the value <else>
	    
		//Replacing indexes with "collection" in name, to check if the dataobject exists in the cmiValid object
		var arrName = name.split(".");
		var arrNewName = new Array();
		var arrCollections = new Array;
		for (var i = 0; i < arrName.length; i++) {
			if (isNaN(arrName[i])==false){
				arrNewName[i] = "collection";
				arrCollections[arrCollections.length] = [i,arrName[i],arrName[i-1]];
			}
			else{
				arrNewName[i] = arrName[i]
			}
		}
		var testName = arrNewName.join(".");
		arrName[0] = "_cmi"; //making _cmi the first element in the datamodel string
		name = arrName.join(".");
		
		//check if _children or _count is used - readOnly
		var bFunction = false;
		if(testName.indexOf("_children")>-1){
			testName = testName.substring(0,testName.indexOf("_children")-1);
			bFunction = true;
		}
		else if(testName.indexOf("_count")>-1){
			testName = testName.substring(0,testName.indexOf("_count")-1);
			bFunction = true;
		}
		
		try{ //if first parameter in the name is not "cmi"
			eval("var oTestObj = this."+ testName);
		}
		catch(exception){
			this.LastError = "401";
			return "false";
		}
		if(oTestObj){
			if(oTestObj.collection){//elementet can't be set
				if(bFunction){
					this.LastError = "404";
					return "false";
				}
				else{
					this.LastError = "351";
					return "false";
				}
			}
			else{ //object exists in cmi datamodel
				if(oTestObj.RW.indexOf("W")>-1){
					try{
						eval("this."+name+" = escapeForLms(value)");
						this.LastError = "0";
						return "true";
					}
					catch(ex){
						return this.handleCollections(arrName,arrCollections,value);
					}
				}
				else{
					this.LastError ="404";
					return "false";
				}
				
			}
		}
		else{//element doesn't exist
			this.LastError = "401";
			return "false";
		}
	}
	
	function _handleCollections(arrName,arrCollections,value){
		var collLength = arrCollections.length;
		if(collLength>0){
			for(var i=collLength-1;i>-1;i--){
				var strTest = "this."
				//if arrCollections[j] is numeric - make indexed instead of json (javascript object notation)
				for(var j=0;j<arrCollections[i][0];j++){
				    if(!isNaN(arrName[j]))
				    {
				        arrName[j] = "[" + arrName[j] + "]"
				    }
				    strTest += arrName[j];
				    if(j<arrCollections[i][0]-1){
					    strTest += "."
				    }				    
				}
				strTest = strTest.replace(".[","[");

				try{
				    
					eval("var oColl = " + strTest);
					if(oColl){//collection object exists
						//collection exists and initialized - with id.
						if(arrName[j]==_count(oColl)){//make new index in array
							if(arrName[j+1]=="id"){
								oColl[arrName[j]] = {id:value}
								this.LastError = "0";
								return "true";
							}
							else{
								this.LastError = "408";
								return "false"
							}
						}
						else if((arrName[j]>_count(oColl))||(arrName[j]<0)){//index out of range
							this.LastError = "351";
							return "false";						
						}
						else{
							if((j+2)==arrName.length){
								eval(strTest+"["+arrName[j]+"]"+"."+arrName[j+1]+"='"+escapeForLms(value)+"'");
								this.LastError = "0";
								return "true";
								
							}
							else{//extra param object element needs to be created - like .score.raw
								if(i<collLength-1){
									var tempArr = new Array();
									//for(var k=i+1;k<collLength; k++){
										if(collLength>i+2){//trying to initialize collection with parent collection not yet initialized
											this.LastError = "403";
											return "false";
										}
										else if(arrCollections[i+1][1]=="0"){
											var collIdx = arrCollections[i+1][0];
											if(arrName[collIdx+1]=="id"){
												strTest += "[" + arrName[collIdx-2] + "]." + arrName[collIdx-1]
												eval(strTest+" = new Array();")
												eval(strTest+"[0] = {"+arrName[collIdx+1]+":'"+escapeForLms(value)+"'};");
												this.LastError = "0";
												return "true"
											}
											else{//trying to initialize new index with other than id
												this.LastError = "408";
												return "false";
											}
										}
										else{//New collection Idx is larger than 0
											this.LastError = "351";
											return "false";
										}
									//}
									eval(strTest+"["+arrName[j]+"]."+arrName[j+1]+" = tempArr;");
								}
								else{
									eval(strTest+"["+arrName[j]+"]."+arrName[j+1]+" = {"+arrName[j+2]+":"+escapeForLms(value)+"}");
								}
							}
						}
					}
					else{//Array needs to be created and initialized
						if(arrName[j+1]=="id" || ( arrName[j] != "interactions" && j>0 ))//initializing collection setting id value
						{
							strTest = strTest.substring(0,strTest.lastIndexOf("."));
						    eval(strTest+"."+arrName[j-1]+" = new Array()")
						    if( value.indexOf("[,]")>-1 )
						    {
						        var arrSubColl = value.split("[,]")
						        for(var k=0; k<arrSubColl.length; k++)
						        {
						            eval(strTest+"."+arrName[j-1]+"["+k+"] = {" + arrName[j+1] + ":'"+escapeForLms(arrSubColl[k])+"'}");
						        }
						    }
						    else
                            {
							    eval(strTest+"."+arrName[j-1]+"[0] = {" + arrName[j+1] + ":'"+escapeForLms(value)+"'}");
							}
							this.LastError = "0";
							return "true";
						}
						else{//trying to set values with collection not initialized
							this.LastError = "408";
							return "false";
						}
					}
				}
				catch(ex){//collection object and parent object doesnt exist
					//alert(strTest)
				}
			}
		}
		else{//not colections
			eval("this."+arrName[0]+" = {"+arrName[1]+":{"+arrName[2]+":"+escapeForLms(value)+"}}");
		}
	}
	
	function _children(oElement){
		var listString = "";
		bCollection = false;
		for(childElement in oElement){
			if(childElement=="collection"){
				listString = "";
				bCollection = true
				for(subChildElement in oElement[childElement]){
					listString += subChildElement + ", ";
				}
			}
			else{
				if((childElement!="methods")&&(!bCollection)){
					listString += childElement + ",";
				}
			}
		}
		return listString.substring(0,listString.length-1);
	}
	
	function _count(oElement){
		return oElement.length;
	}
	
	function _commit(){
	    //Commit can be called several times
	    //What about usersessions, one per commit??
	    if(this.scoUserID != null)
	    {
		    var retVal = this.writeXmlData(this._cmi,this.cmi);
		}
		return "?";
	}
	
	function _getLastError(){
		return this.LastError;
	}
	
	function _getErrorString(id){
		if(this.arrErrorCodes[id]){
			return this.arrErrorCodes[id].name
		}
		else{
			return ""
		}
	}
	
	function _getDiagnostic(id){
		if(arrErrorCodes[id]){
			if(arrErrorCodes[id].diag){
				return arrErrorCodes[id].diag
			}
			else{
				return ""
			}
		}
		else{
			return ""
		}
	}
   
   function _setIsBrowserNetscape(arg){
		this.bNetscape = arg;
   }
   
   function _setTestIDInfo(_scoTitle,_scoVersion,_scoVName){
		this.scoTitle = _scoTitle;
		this.scoVersion = _scoVersion;
		this.scoVName = _scoVName;
   }
   
    function _startTest(scoUserID,scoLocation, LcmsID, LanguageID){
		if(!this.initialized){
			this._cmi = {_version:"1.0"};
		    _jsObjHandle = this;
	        this.scoUserID = scoUserID;
	        this.scoLocation = scoLocation;
	        this.LcmsID = LcmsID;
	        this.LanguageID = LanguageID;
		        
		    if(scoUserID!=null)
		    {
			    getValuesFromLMS(scoUserID, LcmsID);
			}
			else //stand-alone-test
			{
	            this.startTime = new Date();
		        launchSCO(this.scoLocation)
			}
		}
	}
	
	function _endTest(bArg1, bArg2){
		alert("endTest mangler");
	}
	
	function _abortSCOTest(){
		alert("abortSCOTest mangler");
	}
	
	function writeSubXmlData(oElement,oTemplateElement,strXml,_element){
		var strSubElement="";
		var strTmplElement="";
		var arrTags = new Array
		var bWrite = false
		if(typeof(oElement)=="object"){
			if(!isNaN(_element)){
				arrTags[arrTags.length] = "num_"+_element;
			}
			else{
				arrTags[arrTags.length] = _element;
			}
			var subString = "";
			strSubElement = "";
			for(_subElement in oElement){
				if(!isNaN(_subElement)){
					strTmplElement = "collection";
					strSubElement = "num_" + _subElement;
				}
				else{
					strTmplElement = _subElement;
					strSubElement = _subElement;
				}
				if(typeof(oElement[_subElement])=="object"){
					bWrite = true
					//strXml += writeSubXmlData(oElement[_subElement],oTemplateElement[strTmplElement],strXml,strSubElement);
					subString += writeSubXmlData(oElement[_subElement],oTemplateElement[strTmplElement],strXml,strSubElement);
				}
				else if(oTemplateElement[strTmplElement].RW.indexOf("W")>-1){
					bWrite = true
					
					if(oTemplateElement[strTmplElement].type=="CData"){
						subString += "<"+strSubElement+"><![CDATA["+oElement[_subElement]+"]]></"+strSubElement+">";
					}
					else{
						subString += "<"+strSubElement+">"+oElement[_subElement]+"</"+strSubElement+">";
					}
				}
			}
			if(subString!=""){ 
				strXml += subString;
			}
		}
		else if(oTemplateElement.RW.indexOf("W")>-1){
			if(oTemplateElement.type=="CData"){
				strXml += "<"+_element+"><![CDATA["+oElement+"]]></"+_element+">";
			}
			else{
				strXml += "<"+_element+">"+oElement+"</"+_element+">";
			}
		}
		if(!bWrite){
			arrTags.splice(arrTags.length-1,1)
		}
		else if(arrTags.length>0&&strXml!=""){
			strXml = "<" + arrTags[arrTags.length-1] + ">" + strXml + "</" + arrTags[arrTags.length-1] + ">"
			arrTags.splice(arrTags.length-1,1);
		}
		return strXml;
	}
	
	function _writeXmlData(oCmi,oCmiTemplate){
		var strXml = ""
		var arrXml;
		var strSubXml;
		var strElement;
		var strSubElement;
		var sendXmlHttp;
		var strUrl;
		var sessionTime;
		for(_element in oCmi){
			var oElement = oCmi[_element];
			var oTemplateElement = oCmiTemplate[_element];
			strXml += writeSubXmlData(oElement,oTemplateElement,"",_element);
		}

		if(strXml.indexOf("<session_time>")==-1){
			strXml += "<session_time>" + formatTimeInterval(this.startTime,new Date()) + "</session_time>";
		}
		strXml = "<?xml version='1.0' encoding='iso-8859-1'?><cmi>" + strXml + "</cmi>"
		var scoUserID = this.scoUserID;
		var sessionID = this.SessionID;
		this.sendingCmiData = true;
	    MomentumLms.webServices.exchangeDataWithLms.sendData(scoUserID, sessionID, strXml, cmiDataCommited); 
	}
	
	function cmiDataCommited()
	{
	    _jsObjHandle.sendingCmiData = false;
	}
	
	function formatTimeInterval(date1,date2){
		var thisYear = date2.getUTCFullYear();
		var nYears, nMonths, nDays, nHours, nMinutes, nSeconds;
		var daysInThisMonth;
		var remainderInMSec = date2.valueOf() - date1.valueOf()
		var strRetval;
		if(((thisYear%4==0)&&(thisYear%100!=0))||(thisYear%400==0)){
			arrMonths = new Array(31,29,31,30,31,30,31,31,30,31,30,31);
		}
		else{
			arrMonths = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
		}
		daysInThisMonth = (date2.getUTCMonth()>0 ? arrMonths[date2.getUTCMonth()-1] : arrMonths[11]);
		
		nYears  = date2.getUTCFullYear() - date1.getUTCFullYear();
		nMonths = date2.getUTCMonth() - date1.getUTCMonth();
		nDays = date2.getUTCDate() - date1.getUTCDate();
		if(nDays<0){
			nDays = daysInThisMonth + nDays;
			nMonths -= 1;
		}
		if(nMonths<0){
			nYears -= 1;
			nMonths = 12 + nMonths;
		}
		if(remainderInMSec>(24*60*60*1000)){
			remainderInMSec = remainderInMSec%(24*60*60*1000);
		}
		nHours = Math.floor(remainderInMSec/(60*60*1000));
		remainderInMSec = remainderInMSec%(60*60*1000)
		nMinutes = Math.floor(remainderInMSec/(60*1000));
		remainderInMSec = remainderInMSec%(60*1000)
		nSeconds = (Math.round(remainderInMSec/10))/100;

		strRetval = (nHours!=0 ? nHours+"H": "") + (nMinutes!=0 ? nMinutes+"M": "") + (nSeconds!=0 ? nSeconds+"S": "")
		strRetval = "P" + (nYears!=0 ? nYears+"Y": "") + (nMonths!=0 ? nMonths+"M": "") + (nDays!=0 ? nDays+"D": "") + (strRetval!="" ? "T": "") + strRetval;
		
		return strRetval;
	}

	function GetXmlHttpObject(handler){ 
		var _XMLHttp=null;
		try{
			_XMLHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e){
			 try{
			 	_XMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
			 }
			 catch(e){}
		}
		if (_XMLHttp==null)
		{
			_XMLHttp=new XMLHttpRequest();
		}
		return _XMLHttp;
	}
	
	function initCMIData(oXml){
	   
	    oXMlRetval = oXml.documentElement;
	    _jsObjHandle.SessionID = oXMlRetval.childNodes[0].childNodes[0].nodeValue;
		var oNodes = oXMlRetval.childNodes[1].childNodes;
		for (var i = 0; i < oNodes.length; i++) {
			if(oNodes[i].childNodes[0].childNodes.length > 0){
				initCMIColl(oNodes[i],"");
			}
			else{
				eval("_jsObjHandle._cmi." + oNodes[i].tagName + "='" + oNodes[i].childNodes[0].nodeValue+"';");
			}
		}
		//_jsObjHandle.initialized = true;
		_jsObjHandle.startTime = new Date();
		launchSCO(_jsObjHandle.scoLocation)
	}
	
	var bCollInitialized ;
	
	function initCMIColl(oNode, strParNodes){
		var oChildNodes = oNode.childNodes;
		var parNodeName = oNode.nodeName;
		var strParams = "";
		var oColl;
		var arrColl = new Array;
		var strArr = "";
		bCollInitialized = false;
		for (var j = 0; j < oChildNodes.length; j++) {
			if(oChildNodes[j].nodeName.indexOf("num_")>-1){//collections
				oColl = oChildNodes[j].childNodes;
				for(var k = 0; k < oColl.length; k++) {
					if(oColl[k].childNodes[0].childNodes.length > 0){
						initCMIColl(oColl[k],"_jsObjHandle._cmi." + parNodeName+"["+j+"]");
					}
					else{
					    
						if(bCollInitialized){
							if(strParNodes!=""){
								eval(strParNodes+"." + parNodeName+"["+j+"]."+oColl[k].nodeName+"='"+oColl[k].childNodes[0].nodeValue+"'");
							}
							else{
								eval("_jsObjHandle._cmi." + parNodeName+"["+j+"]."+oColl[k].nodeName+"='"+oColl[k].childNodes[0].nodeValue+"'");
							}
						}
						else{
							strArr += oColl[k].nodeName + ":'" + oColl[k].childNodes[0].nodeValue+"',"
						}
					}
				}
				if(strArr!=""){
					eval("arrColl[j] = {" + strArr.substring(0,strArr.length-1) + "}");
					strArr = "";
				}
			}
			else{
			    strParams += oChildNodes[j].nodeName + ":'" + oChildNodes[j].childNodes[0].nodeValue+"',";
			}
		}
		if(strParams.length>0)
		{
			try{
				if (strParNodes!="")
				{
					eval(strParNodes + "." + parNodeName + " = {" + strParams.substring(0,strParams.length-1) + "}");
					
				}
				else
				{
					eval("_jsObjHandle._cmi." + parNodeName + " = {" + strParams.substring(0,strParams.length-1) + "}");
				}
			}
			catch(ex){
				try{	
					var shortName = strParNodes.substring(0,strParNodes.indexOf("["))
					eval(shortName + " = new Array");
					eval(shortName + "[0] = {" + parNodeName + ":{" + strParams.substring(0,strParams.length-1) + "}}")
					bCollInitialized = true;
				}
				catch(ex){
					alert("Data collected from LMS - does not match the SCORM data structure");
				}
			}
		}
		else if(arrColl.length>0&&!bCollInitialized){
			try{
				//hvis den allerede findes løbe igennem array
				eval("_jsObjHandle._cmi." + parNodeName + " = arrColl");
			}
			catch(ex){alert("Data collected from LMS - does not match the SCORM data structure")}
		}
	}

	function getValuesFromLMS(UserID,LcmsID)
	{
	    MomentumLms.webServices.exchangeDataWithLms.getData(UserID, LcmsID,initCMIData,null,"XmlDocument");
	}
   }

//********** END LMSApi javascript object ******************
