diff --git a/src/main/java/org/olat/course/nodes/scorm/ScormRunController.java b/src/main/java/org/olat/course/nodes/scorm/ScormRunController.java
index 25854553a31dbec32005740c0187707cf0ea005e..a1843642f5cfd57984055a24bc627f6e038df627 100644
--- a/src/main/java/org/olat/course/nodes/scorm/ScormRunController.java
+++ b/src/main/java/org/olat/course/nodes/scorm/ScormRunController.java
@@ -369,8 +369,8 @@ public class ScormRunController extends BasicController implements ScormAPICallb
 
 	@Override
 	public void lmsFinish(String olatSahsId, Properties scoreProp, Properties lessonStatusProp) {
+		doStartPage(null);
 		if (config.getBooleanSafe(ScormEditController.CONFIG_CLOSE_ON_FINISH, false)) {
-			doStartPage(null);
 			scormDispC.close();
 		}
 	}
diff --git a/src/main/java/org/olat/modules/scorm/OLATApiAdapter.java b/src/main/java/org/olat/modules/scorm/OLATApiAdapter.java
index 33a027186d4e7362727e98217c00b79af6684c52..d5c752529e857f83d0070dbbae01e303c90e1ebf 100644
--- a/src/main/java/org/olat/modules/scorm/OLATApiAdapter.java
+++ b/src/main/java/org/olat/modules/scorm/OLATApiAdapter.java
@@ -88,8 +88,8 @@ public	class OLATApiAdapter implements ch.ethz.pfplms.scorm.api.ApiAdapterInterf
 	private Properties scoresProp; // keys: sahsId; values = raw score of an sco
 	private Properties lessonStatusProp;
 	
-	private final String SCORE_IDENT = "cmi.core.score.raw";
-	private final String LESSON_STATUS_IDENT = "cmi.core.lesson_status";
+	private static final String SCORE_IDENT = "cmi.core.score.raw";
+	private static final String LESSON_STATUS_IDENT = "cmi.core.lesson_status";
 	private File scorePropsFile;
 	private File lessonStatusPropsFile;
 	
@@ -162,7 +162,7 @@ public	class OLATApiAdapter implements ch.ethz.pfplms.scorm.api.ApiAdapterInterf
 
 	private final void say (String s) {
 		
-			log.debug("core: "+s);
+			log.debug("core: {}", s);
 		
 	}
 
diff --git a/src/main/java/org/olat/modules/scorm/ScormAPIMapper.java b/src/main/java/org/olat/modules/scorm/ScormAPIMapper.java
index 3ef2ae794d6111734dececeae1cdf6572fe9ab48..8834528cce60edf4f3597dc77aca45304824dfd7 100644
--- a/src/main/java/org/olat/modules/scorm/ScormAPIMapper.java
+++ b/src/main/java/org/olat/modules/scorm/ScormAPIMapper.java
@@ -36,12 +36,16 @@ import java.util.Properties;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.logging.log4j.Logger;
+import org.json.JSONArray;
+import org.json.JSONObject;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.modules.bc.FolderConfig;
 import org.olat.core.dispatcher.mapper.Mapper;
 import org.olat.core.gui.media.MediaResource;
+import org.olat.core.gui.media.ServletUtil;
 import org.olat.core.gui.media.StringMediaResource;
 import org.olat.core.id.Identity;
 import org.olat.core.id.IdentityEnvironment;
@@ -322,43 +326,90 @@ public class ScormAPIMapper implements Mapper, ScormAPICallback, Serializable {
 		String apiCallParamTwo = request.getParameter("apiCallParamTwo");
 		
 		if(log.isDebugEnabled()) {
-			log.debug("scorm api request by user:"+ identity.getName() +": " + apiCall + "('" + apiCallParamOne + "' , '" + apiCallParamTwo + "')");
+			log.debug("scorm api request by user: {}: {} ('{}' , '{}')", identity.getName(), apiCall, apiCallParamOne, apiCallParamTwo);
 		}
 
-		StringMediaResource smr = new StringMediaResource();
-		smr.setContentType("text/html");
-		smr.setEncoding("utf-8");
-		
 		if (apiCall != null && apiCall.equals("initcall")) {
 			//used for Mozilla / firefox only to get more time for fireing the onunload stuff triggered by overwriting the content.
-			smr.setData("<html><body></body></html>");
-			return smr;
+			log.info("Init call");
+			return createInitResource(request);
 		}
 
-		String returnValue = "";
 		if (apiCall != null) {
-			if (apiCall.equals(LMS_INITIALIZE)) {
-				returnValue = scormAdapter.LMSInitialize(apiCallParamOne);
-			} else if (apiCall.equals(LMS_GETVALUE)) {
-				returnValue = scormAdapter.LMSGetValue(apiCallParamOne);
-			} else if (apiCall.equals(LMS_SETVALUE)) {
-				returnValue = scormAdapter.LMSSetValue(apiCallParamOne, apiCallParamTwo);
-			} else if (apiCall.equals(LMS_COMMIT)) {
-				returnValue = scormAdapter.LMSCommit(apiCallParamOne);
-			} else if (apiCall.equals(LMS_FINISH)) {
-				returnValue = scormAdapter.LMSFinish(apiCallParamOne);
-			} else if (apiCall.equals(LMS_GETLASTERROR)) {
-				returnValue = scormAdapter.LMSGetLastError();
-			} else if (apiCall.equals(LMS_GETDIAGNOSTIC)) {
-				returnValue = scormAdapter.LMSGetDiagnostic(apiCallParamOne);
-			} else if (apiCall.equals(LMS_GETERRORSTRING)) {
-				returnValue = scormAdapter.LMSGetErrorString(apiCallParamOne);
+			String returnValue = apiCall(apiCall, apiCallParamOne, apiCallParamTwo);
+			return createResource(returnValue, request);
+		} else if(relPath.contains("batch")) {
+			try {				
+				String batch = IOUtils.toString(request.getReader());
+				JSONArray batchArray = new JSONArray(batch);
+				for(int i=0; i<batchArray.length(); i++) {
+					JSONObject obj = batchArray.getJSONObject(i);
+					apiCall = obj.getString("apiCall");
+					apiCallParamOne = obj.getString("param1");
+					apiCallParamTwo = obj.getString("param2");
+					apiCall(apiCall, apiCallParamOne, apiCallParamTwo);
+				}
+			} catch (IOException e) {
+				log.error("", e);
 			}
-			smr.setData("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><p>"
-					+ returnValue + "</p></body></html>");
-			return smr;
 		}
-		smr.setData("");
+		return createResource("", request);
+	}
+	
+	private String apiCall(String apiCall, String apiCallParamOne, String apiCallParamTwo) {
+		String returnValue = "";
+		if (apiCall.equals(LMS_INITIALIZE)) {
+			returnValue = scormAdapter.LMSInitialize(apiCallParamOne);
+		} else if (apiCall.equals(LMS_GETVALUE)) {
+			returnValue = scormAdapter.LMSGetValue(apiCallParamOne);
+		} else if (apiCall.equals(LMS_SETVALUE)) {
+			returnValue = scormAdapter.LMSSetValue(apiCallParamOne, apiCallParamTwo);
+		} else if (apiCall.equals(LMS_COMMIT)) {
+			returnValue = scormAdapter.LMSCommit(apiCallParamOne);
+		} else if (apiCall.equals(LMS_FINISH)) {
+			returnValue = scormAdapter.LMSFinish(apiCallParamOne);
+		} else if (apiCall.equals(LMS_GETLASTERROR)) {
+			returnValue = scormAdapter.LMSGetLastError();
+		} else if (apiCall.equals(LMS_GETDIAGNOSTIC)) {
+			returnValue = scormAdapter.LMSGetDiagnostic(apiCallParamOne);
+		} else if (apiCall.equals(LMS_GETERRORSTRING)) {
+			returnValue = scormAdapter.LMSGetErrorString(apiCallParamOne);
+		}
+		return returnValue;
+	}
+	
+	private MediaResource createInitResource(HttpServletRequest request) {
+		MediaResource resource;
+		boolean acceptJson = ServletUtil.acceptJson(request);
+		if(acceptJson && request == null) {
+			resource = createHTMLResource("");
+		} else {
+			resource = createHTMLResource("<html><body></body></html>");
+		}
+		return resource;
+	}
+	
+	private MediaResource createResource(String returnValue, HttpServletRequest request) {
+		MediaResource resource;
+		boolean acceptJson = ServletUtil.acceptJson(request);
+		if(acceptJson && request == null) {
+			resource = createHTMLResource("");
+			
+		} else if(StringHelper.containsNonWhitespace(returnValue)) {
+			String data = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><p>" + returnValue + "</p></body></html>";
+			resource = createHTMLResource(data);
+		} else {
+			resource = createHTMLResource("");
+		}
+		return resource;
+	}
+	
+
+	private StringMediaResource createHTMLResource(String data) {
+		StringMediaResource smr = new StringMediaResource();
+		smr.setContentType("text/html");
+		smr.setEncoding("utf-8");
+		smr.setData(data);
 		return smr;
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/scorm/ScormAPIandDisplayController.java b/src/main/java/org/olat/modules/scorm/ScormAPIandDisplayController.java
index 8a5b183d4099aa79810c3268713f8ec09621e592..1c0b47ebfec3efd5d6e42a6e33df345fa1f7598c 100644
--- a/src/main/java/org/olat/modules/scorm/ScormAPIandDisplayController.java
+++ b/src/main/java/org/olat/modules/scorm/ScormAPIandDisplayController.java
@@ -29,6 +29,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Properties;
 
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsBackController;
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
@@ -73,7 +74,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  * the sco api calls to the scorm RTE backend. It provides also an navigation to
  * navigate in the tree with "pre" "next" buttons.
  */
-public class ScormAPIandDisplayController extends MainLayoutBasicController implements ConfigurationChangedListener {
+public class ScormAPIandDisplayController extends MainLayoutBasicController implements ConfigurationChangedListener, ScormAPICallback {
 
 	protected static final String LMS_INITIALIZE = "LMSInitialize";
 	protected static final String LMS_GETVALUE = "LMSGetValue";
@@ -136,6 +137,7 @@ public class ScormAPIandDisplayController extends MainLayoutBasicController impl
 		try {
 			scormAdapter = new OLATApiAdapter();	
 			scormAdapter.addAPIListener(apiCallback);
+			scormAdapter.addAPIListener(this);
 			String fullname = UserManager.getInstance().getUserDisplayName(getIdentity());
 			String scormResourceIdStr = scormResourceId == null ? null : scormResourceId.toString();
 			scormAdapter.init(cpRoot, scormResourceIdStr, courseIdNodeId, FolderConfig.getCanonicalRoot(), username, fullname, lesson_mode, credit_mode, hashCode());
@@ -322,6 +324,16 @@ public class ScormAPIandDisplayController extends MainLayoutBasicController impl
 		}		 
 	}
 	
+	@Override
+	public void lmsCommit(String olatSahsId, Properties scoScores, Properties scoLessonStatus) {
+		//
+	}
+
+	@Override
+	public void lmsFinish(String olatSahsId, Properties scoProps, Properties scoLessonStatus) {
+		myContent.setDirty(false);
+	}
+
 	@Override
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if(source == columnLayoutCtr) {
diff --git a/src/main/java/org/olat/modules/scorm/_content/display.html b/src/main/java/org/olat/modules/scorm/_content/display.html
index 813ffd77fe6deb379cdfc4b6f6c31ce3eac84c81..aac190e729de829a9bae99176b60c4a3a9103ccb 100644
--- a/src/main/java/org/olat/modules/scorm/_content/display.html
+++ b/src/main/java/org/olat/modules/scorm/_content/display.html
@@ -10,7 +10,11 @@
 		## method to send a ping to the framework to draw itself after finish
 		function pingAfterFinish() { 
 			window.suppressOlatOnUnloadOnce = true;
-			$r.javaScriptCommand('ping'); 
+			try {
+				$r.javaScriptCommand('ping');
+			} catch(e) {
+				if(window.console) console.log(e);
+			}
 		}
 	</script>
 	<script>
diff --git a/src/main/webapp/static/js/openolat/scormApiAdapter.js b/src/main/webapp/static/js/openolat/scormApiAdapter.js
index 3ae1ef35622a9bafc306758e3d7628eeebd5a947..cd528a20daf3eeea56c28e5f682b490d22e5fa45 100644
--- a/src/main/webapp/static/js/openolat/scormApiAdapter.js
+++ b/src/main/webapp/static/js/openolat/scormApiAdapter.js
@@ -16,137 +16,43 @@ var API = window;
 * right now only used for moz, as ie has some problems with state handler
 * room for improvement by makeing it into one function that works for both
 */
-function scormApiRequest(remoteUrl)
-{
-		this.remoteOLATurl = remoteUrl;
-		this.isMozilla = false;
-		this.httpReq=false;
-		
-		this.reqCount = 0;
-		
-		this.sendSyncSingle	= asSendSyncSingle;
-		if (window.XMLHttpRequest)
-		{
-			this.httpReq = new XMLHttpRequest();
-			this.isMozilla = true;
-			if (debug) dump("func:scormApiRequest :is Mozilla\n");
-		}
-		// code for IE
-		else if (window.ActiveXObject)
-		{
-			try {
-				this.httpReq = new ActiveXObject("Msxml2.XMLHTTP");
-				if (debug) dump("func:scormApiRequest :is new IE \n");
-			} catch (e) {
-				try {
-					this.httpReq = new ActiveXObject("Microsoft.XMLHTTP");
-					if (debug) dump("func:scormApiRequest :is old IE \n");
-				} catch (E) {
-					this.httpReq = false;
-				}
-			}
-		}
-}
-
-function asSendSyncSingle(apiCall, param1, param2) {
-	// Sync - wait until data arrives
-	//IE does not like this function, what's it for?
-	//httpReq.multipart	= false;
-
-	// Mozilla/Firefox bug 246518 workaround
-	// a new XMLHttpRequest object if needed
-	try {
-		this.httpReq.onload = showReq;
-		this.httpReq.onreadystatechange = showReq;
-		this.httpReq.open('POST', this.remoteOLATurl, false );
-	} catch (e) {
-		this.httpReq = new XMLHttpRequest();
-		this.httpReq.onload = showReq;
-		this.httpReq.onreadystatechange = showReq;
-		this.httpReq.open('POST', this.remoteOLATurl, false );
-	  }
-
-	this.httpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8'); 
-	this.httpReq.send('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
-	if(this.isMozilla)
-	{
-		if (debug) dump("func:asSencSingle: post successfull, calling showReq\n");
-		
-		//add event listener geht auch! ev. besser?
-		//httpReq.addEventListener("load", showReq, false)
-		//this.httpReq.onload = showReq;
-		//this.httpReq.onreadystatechange = showReq;
-	} else {
-		if (debug) dump("func:asSencSingle: post successfull by this.httpReq, calling showReq\n");
-		//this.httpReq.onload = showReq;
-		//this.httpReq.onreadystatechange = showReq;
-	}
-	//httpReq.send(null);
-}
-
-
-function showReq( event ) {
-	if (debug) dump("func:showReq: inside func.: event type: " +event.type+"\n");
-	// ready state 4 means document loaded
-	//if ( event.target.readyState == 4 ) 
-	if ( this.readyState == 4 ) 
-	{
-		bMsg = document.getElementById( 'apiReturnHandler' );
-		//bMsg.innerHTML = event.target.responseText;
-		bMsg.innerHTML = this.responseText;
-		bMsg = null;
-		if (debug) dump("func:showReq: "+this.responseText+"\n");
-	} else { if (debug) dump( 'an error occured! Wrong readyState: ' + event.target.readyState +"\n"); }
+function scormApiRequest(remoteUrl) {
+	this.remoteOLATurl = remoteUrl;
+	this.reqCount = 0;
 }
 	
 	
 /*************************************/
 
-// global flag
-var isIE = false;
-
-// global request and XML document objects
-var scormRTEresponse;
 
 // retrieve XML document (reusable generic function);
-function loadHTMLDoc(url,apiCall, param1, param2) {
-	var req;
-	// inner callback method to handle onreadystatechange event of req object
-	var processReqChange = function (event){	
+function loadHTMLDoc(url, async, apiCall, param1, param2) {
+    var scormResponse;
+    var req = new XMLHttpRequest();
+	req.onreadystatechange = function (event) {	
 		// only if req shows "loaded"
 		if (req.readyState == 4) {
 			// only if "OK"
 			if (req.status == 200) {
-				rteResponseText = req.responseText;
-				scormRTEresponse = rteResponseText.substring(rteResponseText.indexOf("<p>")+3,rteResponseText.indexOf("</p>")); 
-				if (debug) dump(scormRTEresponse);
-			} else { if (debug) dump("There was a problem retrieving the XMLHttpRequest data:\n"+ req.statusText+"\n"); }
+				scormResponse = loadHTMLDocExtractResponse(req.responseText);
+				if (debug) dump(scormResponse);
+			} else if (debug) {
+				dump("There was a problem retrieving the XMLHttpRequest data:\n"+ req.statusText+"\n");
+			}
 		}
 	};
-    // branch for native XMLHttpRequest object
-    if (window.XMLHttpRequest) {
-        req = new XMLHttpRequest();
-		req.onreadystatechange = processReqChange;
-        //req.open("GET", url+'?apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ param2, false);
-        req.open("POST", url, false)
-        req.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8'); 
-        req.send('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
-        if (debug) dump('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
-    // branch for IE/Windows ActiveX version
-    } else if (window.ActiveXObject) {
-        isIE = true;
-        req = new ActiveXObject("Microsoft.XMLHTTP");
-        if (req) {
-            req.onreadystatechange = processReqChange;
-            //req.open("GET", url+'?apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ param2 + '&rnd='+increment(), false);
-            //req.send();
-            req.open("POST", url, false);
-        	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8'); 
-        	req.send('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
-        }
-    }
-    // Help GC
-    req = null;
+    req.open("POST", url, async);
+    req.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8'); 
+    req.send('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
+    if (debug) dump('apiCall='+ apiCall + '&apiCallParamOne='+ param1 + '&apiCallParamTwo='+ encodeURIComponent(param2));
+    return scormResponse;
+}
+
+function loadHTMLDocExtractResponse(responseText) {
+	if("<html><body></body></html>" == responseText) {
+		return "";// initial call
+	}
+	return responseText.substring(responseText.indexOf("<p>") + 3, responseText.indexOf("</p>"));
 }
 
 /*****************************************************************
@@ -164,20 +70,15 @@ function increment(){
 * over a synchronous XmlHttpRequest.
 * Code uses different ways for moz and ie.
 *******************************************************************/
-function passApiCall(apiCall, param1, param2){
-	if(window.ActiveXObject || (navigator.userAgent.indexOf("Safari") != -1)){
-		loadHTMLDoc(olatCommandUri,apiCall,param1,param2);
-		return scormRTEresponse;
-	}else if(window.XMLHttpRequest && (navigator.userAgent.indexOf("Mozilla") != -1)){
-		jsHttpRequest.sendSyncSingle(apiCall,param1, param2);
-		var responseHTML = document.getElementById( 'apiReturnHandler' ).innerHTML;
-		return responseHTML.substring(responseHTML.indexOf("<p>")+3,responseHTML.indexOf("</p>"));
-	}else{
-		if (debug) dump("Browser does not support the needed XmlHttpRequest\n");
+
+function passApiCall(apiCall, param1, param2) {
+	try {
+		return loadHTMLDoc(olatCommandUri, false, apiCall, param1, param2);
+	} catch(e) {
+		if(window.console) console.log(e);
 	}
 }
 
-
 /**
 * triggers the onunload stuff often used in scorm content to finish an sco by
 * opening the iframe document for writing (IE) or replacing the content doc (Mozilla).
@@ -185,34 +86,27 @@ function passApiCall(apiCall, param1, param2){
 function olatonunload(){
 	if (debug) dump("func:olatonunload: is called\n");
 	if(window.frameId && document.getElementById(frameId) && this.frames[frameId]){
-		if(window.ActiveXObject){
-			//on IE by opening the document, the onunload event gets triggered
-			var iframeDoc = this.frames[frameId].document;
-			iframeDoc.open();
-			iframeDoc.write("<html><body></body></html>");
-			iframeDoc.close();
-			iframeDoc = null;
-		} else {
-			// Mozilla and others
-			var iframeDoc = document.getElementById(frameId).contentDocument;
-			iframeDoc.location.replace("about:blank");
-			iframeDoc = null;
-			//delay(200);
-			//if((new Date().getTime() - lastRequest) > 60000) alert("Current SCO will be finished before initializing next SCO or terminating! Press OK to proceed.");
-			
-			var delayReq = new XMLHttpRequest();
-			//"false" waits until the result arrived;
-			delayReq.open('GET', olatCommandUri, false );
-			delayReq.send(null);
-		}
+		// Mozilla and others
+		var iframeDoc = document.getElementById(frameId).contentDocument;
+		iframeDoc.location.replace("about:blank");
+		iframeDoc = null;
+		
+		var delayReq = new XMLHttpRequest();
+		//"false" waits until the result arrived;
+		delayReq.open('GET', olatCommandUri, false );
+		delayReq.send(null);
 	}
 	return true;
 }
-function delay(gap){
-	var then,now; then=new Date().getTime();
-	now=then;
-	while((now-then)<gap)
-	{now=new Date().getTime();}
+
+var openolatScormUnloadQueue = new Array();
+
+function queueCall(apiCall, param1, param2) {
+	var entry = new Object();
+	entry.apiCall = apiCall;
+	entry.param1 = param1;
+	entry.param2 = param2;
+	openolatScormUnloadQueue.push(entry);
 }
 
 /******************************************************************
@@ -224,7 +118,14 @@ function LMSInitialize (s) {
 	return passApiCall('LMSInitialize',s,'');
 }
 function LMSFinish (s) {
-	var finishedResult = passApiCall('LMSFinish',s,'');
+	var finishedResult = passApiCall('LMSFinish', s, '');
+	if(typeof val === "undefined") {
+		// Communication problem, try to send all queued data as beacon
+		queueCall('LMSFinish', s, '');
+		var data = JSON.stringify(openolatScormUnloadQueue);
+		openolatScormUnloadQueue = new Array();
+		navigator.sendBeacon(olatCommandUri + "/batch/data/", data);
+	}
 	// Immediately close module, ping OpenOlat main window to take over control
 	setTimeout(function(){
 		try {
@@ -236,20 +137,38 @@ function LMSFinish (s) {
 	return finishedResult;
 }
 function LMSSetValue (l, r) {
-	return passApiCall('LMSSetValue',l,r);
+	var val = passApiCall('LMSSetValue',l,r);
+	if(typeof val === "undefined") {
+		queueCall('LMSSetValue', l, r);
+		val = r;
+	}
+	return val;
 }
 function LMSGetValue (s) {
 	return passApiCall('LMSGetValue',s,'');
 }
 function LMSGetLastError () {
-	return passApiCall('LMSGetLastError','','');
+	var val = passApiCall('LMSGetLastError','','');
+	if(typeof val === "undefined") {
+		val = "0";
+	}
+	return val;
 }
 function LMSGetErrorString (s) {
-	return passApiCall('LMSGetErrorString',s,'');
+	var val = passApiCall('LMSGetErrorString',s,'');
+	if(typeof val === "undefined") {
+		val = "No Error";
+	}
+	return val;
 }
 function LMSGetDiagnostic (s) {
 	return passApiCall('LMSGetDiagnostic',s,'');
 }
 function LMSCommit (s) {
-	return passApiCall('LMSCommit',s,'');
+	var val = passApiCall('LMSCommit',s,'');
+	if(typeof val === "undefined") {
+		queueCall('LMSCommit', s, '');
+		val = r;
+	}
+	return val;
 }
\ No newline at end of file