Index: /issm/trunk-jpl/src/m/classes/clusters/generic.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/generic.js	(revision 20596)
+++ /issm/trunk-jpl/src/m/classes/clusters/generic.js	(revision 20597)
@@ -47,19 +47,38 @@
 	this.UploadAndRun = function (md,callbackfunction,fid,toolkitsstring,solutionstring,name,runtimename) { //{{{
 
-		var oReq = new XMLHttpRequest();
-		oReq.open("POST", this.url, true);
-		oReq.responseType = 'application/octet-stream';
-		oReq.position = 0
-	
-		//TODO: dynamic progress update with package lengths and parsing
-		oReq.onprogress = function (oEvent) {
-			var newResponse = oReq.responseText;
-			if (newResponse.length == 13) { //"Starting" length as encoded in base64 length
-				$(".run-button").html("COMPUTING...").prop("disabled", true);
-				console.log("base64 repsonse: " + newResponse + " string response: " + window.atob(oReq.responseText));
+		var request = new XMLHttpRequest();
+		$(".run-button").html("CONNECTING...").prop("disabled", true);
+		request.position = 0; //Keep track of current parsing position in repsonseText
+		//TODO: Test timeout conditions (timeout will trigger even if ocnnection is successful, if computation takes too long)
+		request.timeout = 3000;
+		request.ontimeout = function (event) {
+			$(".run-button").html("RUN").prop("disabled", false);
+		}
+		
+		request.upload.onprogress = function(event) {
+			var progress = (event.loaded / event.total * 100).toFixed(0);
+			$(".run-button").html("UPLOADING: " + progress + "%");
+        }
+
+		request.onprogress = function (event) {
+			//Receive updates by parsing message length as a 32-bit hex string of form 0x*09ABCDEF))
+			var startIndex = request.position;
+			var endIndex = request.position + 10;
+			if (request.responseText.length >= endIndex) { //Ensure entire hex string is loaded
+				var chunkSize = parseInt(request.responseText.slice(startIndex, endIndex));
+				startIndex = endIndex;
+				endIndex = startIndex + chunkSize;
+				if (chunkSize >= 65535) { //Arbitrary maximium size of message (Must be below minimium size of model results)
+					$(".run-button").html("DOWNLOADING: " + ((request.responseText.length - request.position) / chunkSize * 100).toFixed(0) + "%").prop("disabled", true);
+				}
+				else if (request.responseText.length >= endIndex) { //Ensure entire chunk is loaded
+					var responseChunk = request.responseText.slice(startIndex, endIndex);
+					$(".run-button").html(responseChunk);
+					request.position = endIndex;
+				}
 			}
 		};
 		
-		oReq.onload = function (oEvent) {
+		request.onload = function (event) {
 			//get context to this.str2ab to avoid duplciation
 			function str2ab(str) {
@@ -70,5 +89,6 @@
 				return buf;
 			} //}}}
-			var buffer2 = str2ab(window.atob(oReq.responseText.slice(13)));			
+			//if (request.responseText.slice(request.position, request.position + 1) == "0x") request.position = request.position + 10;
+			var buffer2 = str2ab(window.atob(request.responseText.slice(request.position + 10)));			
 			var returnBuffer = new Uint8Array(buffer2);
 			var returnBuffer_size=returnBuffer.byteLength;
@@ -79,4 +99,5 @@
 				console.log(e);
 			}
+			$(".run-button").html("RUN").prop("disabled", false);
 			callbackfunction();
 		};
@@ -102,6 +123,5 @@
 		solutionlength[0] = solutionbuffer.byteLength;
 		
-		var binbuffer = new Uint8Array(fid.rawbuffer());
-		//var binbuffer = new Uint16Array(fid.rawbuffer()); seems that 16 array bytes length could be incompatible.
+		var binbuffer = new Uint8Array(fid.rawbuffer()); //seems that 16 array bytes length could be incompatible.
 
 
@@ -111,5 +131,8 @@
 		var data = new Blob([nplength,npbuffer,runtimenamelength,runtimenamebuffer,namelength,namebuffer,toolkitslength,toolkitsbuffer,solutionlength,solutionbuffer,binlength,binbuffer]);
 		//if (typeof(download) != "undefined") download(fid.rawbuffer());
-		oReq.send(data);
+	
+		request.open("POST", this.url, true);
+		request.responseType = 'application/octet-stream';
+		request.send(data);
 		
 		return;
