changeset 2504:642dc3224962

Merge branch 'master' of https://github.com/BrechtDeMan/WebAudioEvaluationTool
author www-data <www-data@sucuk.dcs.qmul.ac.uk>
date Wed, 21 Sep 2016 13:21:06 +0100
parents 4d8b4f60f589 (current diff) 42abe6eddfb5 (diff)
children 52c819e710ca
files
diffstat 5 files changed, 2167 insertions(+), 2268 deletions(-) [+]
line wrap: on
line diff
--- a/interfaces/AB.js	Wed Sep 21 10:20:57 2016 +0100
+++ b/interfaces/AB.js	Wed Sep 21 13:21:06 2016 +0100
@@ -329,7 +329,7 @@
             if (this.parent.specification.parent.playOne || specification.playOne) {
                 $('.comparator-button').text('Wait');
                 $('.comparator-button').attr("disabled","true");
-                $(this.playback).css("disabled","false");
+                $(this.playback).removeAttr("disabled");
             } else {
                 $('.comparator-button').text('Listen');
             }
--- a/interfaces/ABX.js	Wed Sep 21 10:20:57 2016 +0100
+++ b/interfaces/ABX.js	Wed Sep 21 13:21:06 2016 +0100
@@ -323,7 +323,7 @@
             if (this.parent.specification.parent.playOne || specification.playOne) {
                 $('.comparator-button').text('Wait');
                 $('.comparator-button').attr("disabled","true");
-                $(this.playback).css("disabled","false");
+                $(this.playback).removeAttr("disabled");
             } else {
                 $('.comparator-button').text('Listen');
             }
--- a/js/core.js	Wed Sep 21 10:20:57 2016 +0100
+++ b/js/core.js	Wed Sep 21 13:21:06 2016 +0100
@@ -33,9 +33,10 @@
 function escapeHTML(s) {
     return s.split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
 }
+
 function qualifyURL(url) {
-    var el= document.createElement('div');
-    el.innerHTML= '<a href="'+escapeHTML(url)+'">x</a>';
+    var el = document.createElement('div');
+    el.innerHTML = '<a href="' + escapeHTML(url) + '">x</a>';
     return el.firstChild.href;
 }
 
@@ -43,26 +44,21 @@
 // and there is no searchAll style command, this custom function will
 // search all children recusrively for the name. Used for XSD where all
 // element nodes must have a name and therefore can pull the schema node
-XMLDocument.prototype.getAllElementsByName = function(name)
-{
+XMLDocument.prototype.getAllElementsByName = function (name) {
     name = String(name);
     var selected = this.documentElement.getAllElementsByName(name);
     return selected;
 }
 
-Element.prototype.getAllElementsByName = function(name)
-{
+Element.prototype.getAllElementsByName = function (name) {
     name = String(name);
     var selected = [];
     var node = this.firstElementChild;
-    while(node != null)
-    {
-        if (node.getAttribute('name') == name)
-        {
+    while (node != null) {
+        if (node.getAttribute('name') == name) {
             selected.push(node);
         }
-        if (node.childElementCount > 0)
-        {
+        if (node.childElementCount > 0) {
             selected = selected.concat(node.getAllElementsByName(name));
         }
         node = node.nextElementSibling;
@@ -70,26 +66,21 @@
     return selected;
 }
 
-XMLDocument.prototype.getAllElementsByTagName = function(name)
-{
+XMLDocument.prototype.getAllElementsByTagName = function (name) {
     name = String(name);
     var selected = this.documentElement.getAllElementsByTagName(name);
     return selected;
 }
 
-Element.prototype.getAllElementsByTagName = function(name)
-{
+Element.prototype.getAllElementsByTagName = function (name) {
     name = String(name);
     var selected = [];
     var node = this.firstElementChild;
-    while(node != null)
-    {
-        if (node.nodeName == name)
-        {
+    while (node != null) {
+        if (node.nodeName == name) {
             selected.push(node);
         }
-        if (node.childElementCount > 0)
-        {
+        if (node.childElementCount > 0) {
             selected = selected.concat(node.getAllElementsByTagName(name));
         }
         node = node.nextElementSibling;
@@ -99,15 +90,12 @@
 
 // Firefox does not have an XMLDocument.prototype.getElementsByName
 if (typeof XMLDocument.prototype.getElementsByName != "function") {
-    XMLDocument.prototype.getElementsByName = function(name)
-    {
+    XMLDocument.prototype.getElementsByName = function (name) {
         name = String(name);
         var node = this.documentElement.firstElementChild;
         var selected = [];
-        while(node != null)
-        {
-            if (node.getAttribute('name') == name)
-            {
+        while (node != null) {
+            if (node.getAttribute('name') == name) {
                 selected.push(node);
             }
             node = node.nextElementSibling;
@@ -116,68 +104,78 @@
     }
 }
 
-var check_dependancies = function() {
+var check_dependancies = function () {
     // This will check for the data dependancies
-    if (typeof(jQuery) != "function") {return false;}
-    if (typeof(Specification) != "function") {return false;}
-    if (typeof(calculateLoudness) != "function") {return false;}
-    if (typeof(WAVE) != "function") {return false;}
-    if (typeof(validateXML) != "function") {return false;}
+    if (typeof (jQuery) != "function") {
+        return false;
+    }
+    if (typeof (Specification) != "function") {
+        return false;
+    }
+    if (typeof (calculateLoudness) != "function") {
+        return false;
+    }
+    if (typeof (WAVE) != "function") {
+        return false;
+    }
+    if (typeof (validateXML) != "function") {
+        return false;
+    }
     return true;
 }
 
-var onload = function() {
-	// Function called once the browser has loaded all files.
-	// This should perform any initial commands such as structure / loading documents
-	
-	// Create a web audio API context
-	// Fixed for cross-browser support
-	var AudioContext = window.AudioContext || window.webkitAudioContext;
-	audioContext = new AudioContext;
-	
-	// Create test state
-	testState = new stateMachine();
-	
-	// Create the popup interface object
-	popup = new interfacePopup();
-    
+var onload = function () {
+    // Function called once the browser has loaded all files.
+    // This should perform any initial commands such as structure / loading documents
+
+    // Create a web audio API context
+    // Fixed for cross-browser support
+    var AudioContext = window.AudioContext || window.webkitAudioContext;
+    audioContext = new AudioContext;
+
+    // Create test state
+    testState = new stateMachine();
+
+    // Create the popup interface object
+    popup = new interfacePopup();
+
     // Create the specification object
-	specification = new Specification();
-	
-	// Create the interface object
-	interfaceContext = new Interface(specification);
-	
-	// Create the storage object
-	storage = new Storage();
-	// Define window callbacks for interface
-	window.onresize = function(event){interfaceContext.resizeWindow(event);};
-    
-    if (window.location.search.length != 0)
-    {
+    specification = new Specification();
+
+    // Create the interface object
+    interfaceContext = new Interface(specification);
+
+    // Create the storage object
+    storage = new Storage();
+    // Define window callbacks for interface
+    window.onresize = function (event) {
+        interfaceContext.resizeWindow(event);
+    };
+
+    if (window.location.search.length != 0) {
         var search = window.location.search.split('?')[1];
         // Now split the requests into pairs
         var searchQueries = search.split('&');
 
-        for (var i in searchQueries)
-        {
+        for (var i in searchQueries) {
             // Split each key-value pair
             searchQueries[i] = searchQueries[i].split('=');
             var key = searchQueries[i][0];
             var value = decodeURIComponent(searchQueries[i][1]);
-            switch(key) {
-            case "url":
-                url = value;
-                break;
-            case "returnURL":
-                gReturnURL = value;
-                break;
-            case "saveFilenamePrefix":
-                gSaveFilenamePrefix = value;
-                break;
+            switch (key) {
+                case "url":
+                    url = value;
+                    break;
+                case "returnURL":
+                    gReturnURL = value;
+                    break;
+                case "saveFilenamePrefix":
+                    gSaveFilenamePrefix = value;
+                    break;
             }
         }
         loadProjectSpec(url);
-        window.onbeforeunload = function() {
+        window.onbeforeunload = function () {
             return "Please only leave this page once you have completed the tests. Are you sure you have completed all testing?";
         };
     }
@@ -185,21 +183,20 @@
 };
 
 function loadProjectSpec(url) {
-	// Load the project document from the given URL, decode the XML and instruct audioEngine to get audio data
-	// If url is null, request client to upload project XML document
-	var xmlhttp = new XMLHttpRequest();
-	xmlhttp.open("GET",'xml/test-schema.xsd',true);
-	xmlhttp.onload = function()
-	{
-		schemaXSD = xmlhttp.response;
-		var parse = new DOMParser();
-		specification.schema = parse.parseFromString(xmlhttp.response,'text/xml');
-		var r = new XMLHttpRequest();
-		r.open('GET',url,true);
-		r.onload = function() {
-			loadProjectSpecCallback(r.response);
-		};
-        r.onerror = function() {
+    // Load the project document from the given URL, decode the XML and instruct audioEngine to get audio data
+    // If url is null, request client to upload project XML document
+    var xmlhttp = new XMLHttpRequest();
+    xmlhttp.open("GET", 'xml/test-schema.xsd', true);
+    xmlhttp.onload = function () {
+        schemaXSD = xmlhttp.response;
+        var parse = new DOMParser();
+        specification.schema = parse.parseFromString(xmlhttp.response, 'text/xml');
+        var r = new XMLHttpRequest();
+        r.open('GET', url, true);
+        r.onload = function () {
+            loadProjectSpecCallback(r.response);
+        };
+        r.onerror = function () {
             document.getElementsByTagName('body')[0].innerHTML = null;
             var msg = document.createElement("h3");
             msg.textContent = "FATAL ERROR";
@@ -208,56 +205,54 @@
             document.getElementsByTagName('body')[0].appendChild(msg);
             document.getElementsByTagName('body')[0].appendChild(span);
         }
-		r.send();
-	};
-	xmlhttp.send();
+        r.send();
+    };
+    xmlhttp.send();
 };
 
 function loadProjectSpecCallback(response) {
-	// Function called after asynchronous download of XML project specification
-	//var decode = $.parseXML(response);
-	//projectXML = $(decode);
-	
+    // Function called after asynchronous download of XML project specification
+    //var decode = $.parseXML(response);
+    //projectXML = $(decode);
+
     // Check if XML is new or a resumption
     var parse = new DOMParser();
-	var responseDocument = parse.parseFromString(response,'text/xml');
+    var responseDocument = parse.parseFromString(response, 'text/xml');
     var errorNode = responseDocument.getElementsByTagName('parsererror');
-	if (errorNode.length >= 1)
-	{
-		var msg = document.createElement("h3");
-		msg.textContent = "FATAL ERROR";
-		var span = document.createElement("span");
-		span.textContent = "The XML parser returned the following errors when decoding your XML file";
-		document.getElementsByTagName('body')[0].innerHTML = null;
-		document.getElementsByTagName('body')[0].appendChild(msg);
-		document.getElementsByTagName('body')[0].appendChild(span);
-		document.getElementsByTagName('body')[0].appendChild(errorNode[0]);
-		return;
-	}
+    if (errorNode.length >= 1) {
+        var msg = document.createElement("h3");
+        msg.textContent = "FATAL ERROR";
+        var span = document.createElement("span");
+        span.textContent = "The XML parser returned the following errors when decoding your XML file";
+        document.getElementsByTagName('body')[0].innerHTML = null;
+        document.getElementsByTagName('body')[0].appendChild(msg);
+        document.getElementsByTagName('body')[0].appendChild(span);
+        document.getElementsByTagName('body')[0].appendChild(errorNode[0]);
+        return;
+    }
     if (responseDocument == undefined || responseDocument.firstChild == undefined) {
         var msg = document.createElement("h3");
-		msg.textContent = "FATAL ERROR";
-		var span = document.createElement("span");
-		span.textContent = "The project XML was not decoded properly, try refreshing your browser and clearing caches. If the problem persists, contact the test creator.";
-		document.getElementsByTagName('body')[0].innerHTML = null;
-		document.getElementsByTagName('body')[0].appendChild(msg);
-		document.getElementsByTagName('body')[0].appendChild(span);
-		return;
+        msg.textContent = "FATAL ERROR";
+        var span = document.createElement("span");
+        span.textContent = "The project XML was not decoded properly, try refreshing your browser and clearing caches. If the problem persists, contact the test creator.";
+        document.getElementsByTagName('body')[0].innerHTML = null;
+        document.getElementsByTagName('body')[0].appendChild(msg);
+        document.getElementsByTagName('body')[0].appendChild(span);
+        return;
     }
     if (responseDocument.firstChild.nodeName == "waet") {
         // document is a specification
-        
+
         // Perform XML schema validation
         var Module = {
             xml: response,
             schema: schemaXSD,
-            arguments:["--noout", "--schema", 'test-schema.xsd','document.xml']
+            arguments: ["--noout", "--schema", 'test-schema.xsd', 'document.xml']
         };
-            projectXML = responseDocument;
+        projectXML = responseDocument;
         var xmllint = validateXML(Module);
         console.log(xmllint);
-        if(xmllint != 'document.xml validates\n')
-        {
+        if (xmllint != 'document.xml validates\n') {
             document.getElementsByTagName('body')[0].innerHTML = null;
             var msg = document.createElement("h3");
             msg.textContent = "FATAL ERROR";
@@ -266,8 +261,7 @@
             document.getElementsByTagName('body')[0].appendChild(msg);
             document.getElementsByTagName('body')[0].appendChild(span);
             xmllint = xmllint.split('\n');
-            for (var i in xmllint)
-            {
+            for (var i in xmllint) {
                 document.getElementsByTagName('body')[0].appendChild(document.createElement('br'));
                 var span = document.createElement("span");
                 span.textContent = xmllint[i];
@@ -276,13 +270,13 @@
             return;
         }
         // Build the specification
-	   specification.decode(projectXML);
+        specification.decode(projectXML);
         // Generate the session-key
         storage.initialise();
-        
+
     } else if (responseDocument.firstChild.nodeName == "waetresult") {
         // document is a result
-        projectXML = document.implementation.createDocument(null,"waet");
+        projectXML = document.implementation.createDocument(null, "waet");
         projectXML.firstChild.appendChild(responseDocument.getElementsByTagName('waet')[0].getElementsByTagName("setup")[0].cloneNode(true));
         var child = responseDocument.firstChild.firstChild;
         while (child != null) {
@@ -292,7 +286,7 @@
                     // We need to remove this survey from <setup>
                     var location = child.getAttribute("location");
                     var globalSurveys = projectXML.getElementsByTagName("setup")[0].getElementsByTagName("survey")[0];
-                    while(globalSurveys != null) {
+                    while (globalSurveys != null) {
                         if (location == "pre" || location == "before") {
                             if (globalSurveys.getAttribute("location") == "pre" || globalSurveys.getAttribute("location") == "before") {
                                 projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys);
@@ -324,26 +318,25 @@
             child = child.nextElementSibling;
         }
         // Build the specification
-	    specification.decode(projectXML);
+        specification.decode(projectXML);
         // Use the original
         storage.initialise(responseDocument);
     }
-	/// CHECK FOR SAMPLE RATE COMPATIBILITY
-	if (specification.sampleRate != undefined) {
-		if (Number(specification.sampleRate) != audioContext.sampleRate) {
-			var errStr = 'Sample rates do not match! Requested '+Number(specification.sampleRate)+', got '+audioContext.sampleRate+'. Please set the sample rate to match before completing this test.';
-            interfaceContext.lightbox.post("Error",errStr);
-			return;
-		}
-	}
-	
-	// Detect the interface to use and load the relevant javascripts.
-	var interfaceJS = document.createElement('script');
-	interfaceJS.setAttribute("type","text/javascript");
-	switch(specification.interface)
-	{
-		case "APE":
-            interfaceJS.setAttribute("src","interfaces/ape.js");
+    /// CHECK FOR SAMPLE RATE COMPATIBILITY
+    if (specification.sampleRate != undefined) {
+        if (Number(specification.sampleRate) != audioContext.sampleRate) {
+            var errStr = 'Sample rates do not match! Requested ' + Number(specification.sampleRate) + ', got ' + audioContext.sampleRate + '. Please set the sample rate to match before completing this test.';
+            interfaceContext.lightbox.post("Error", errStr);
+            return;
+        }
+    }
+
+    // Detect the interface to use and load the relevant javascripts.
+    var interfaceJS = document.createElement('script');
+    interfaceJS.setAttribute("type", "text/javascript");
+    switch (specification.interface) {
+        case "APE":
+            interfaceJS.setAttribute("src", "interfaces/ape.js");
 
             // APE comes with a css file
             var css = document.createElement('link');
@@ -354,8 +347,8 @@
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
 
-		case "MUSHRA":
-            interfaceJS.setAttribute("src","interfaces/mushra.js");
+        case "MUSHRA":
+            interfaceJS.setAttribute("src", "interfaces/mushra.js");
 
             // MUSHRA comes with a css file
             var css = document.createElement('link');
@@ -365,9 +358,9 @@
 
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
-		
-		case "AB":
-            interfaceJS.setAttribute("src","interfaces/AB.js");
+
+        case "AB":
+            interfaceJS.setAttribute("src", "interfaces/AB.js");
 
             // AB comes with a css file
             var css = document.createElement('link');
@@ -377,9 +370,9 @@
 
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
-            
+
         case "ABX":
-            interfaceJS.setAttribute("src","interfaces/ABX.js");
+            interfaceJS.setAttribute("src", "interfaces/ABX.js");
 
             // AB comes with a css file
             var css = document.createElement('link');
@@ -389,14 +382,14 @@
 
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
-        
-		case "Bipolar":
-		case "ACR":
-		case "DCR":
-		case "CCR":
-		case "ABC":
+
+        case "Bipolar":
+        case "ACR":
+        case "DCR":
+        case "CCR":
+        case "ABC":
             // Above enumerate to horizontal sliders
-            interfaceJS.setAttribute("src","interfaces/horizontal-sliders.js");
+            interfaceJS.setAttribute("src", "interfaces/horizontal-sliders.js");
 
             // horizontal-sliders comes with a css file
             var css = document.createElement('link');
@@ -406,10 +399,10 @@
 
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
-		case "discrete":
-		case "likert":
+        case "discrete":
+        case "likert":
             // Above enumerate to horizontal discrete radios
-            interfaceJS.setAttribute("src","interfaces/discrete.js");
+            interfaceJS.setAttribute("src", "interfaces/discrete.js");
 
             // horizontal-sliders comes with a css file
             var css = document.createElement('link');
@@ -420,7 +413,7 @@
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
         case "timeline":
-            interfaceJS.setAttribute("src","interfaces/timeline.js");
+            interfaceJS.setAttribute("src", "interfaces/timeline.js");
             var css = document.createElement('link');
             css.rel = 'stylesheet';
             css.type = 'text/css';
@@ -428,64 +421,66 @@
 
             document.getElementsByTagName("head")[0].appendChild(css);
             break;
-	}
-	document.getElementsByTagName("head")[0].appendChild(interfaceJS);
-    
+    }
+    document.getElementsByTagName("head")[0].appendChild(interfaceJS);
+
     if (gReturnURL != undefined) {
-        console.log("returnURL Overide from "+specification.returnURL+" to "+gReturnURL);
+        console.log("returnURL Overide from " + specification.returnURL + " to " + gReturnURL);
         specification.returnURL = gReturnURL;
     }
-    if (gSaveFilenamePrefix != undefined){
+    if (gSaveFilenamePrefix != undefined) {
         specification.saveFilenamePrefix = gSaveFilenamePrefix;
     }
-	
-	// Create the audio engine object
-	audioEngineContext = new AudioEngine(specification);
+
+    // Create the audio engine object
+    audioEngineContext = new AudioEngine(specification);
 }
 
 function createProjectSave(destURL) {
     // Clear the window.onbeforeunload
     window.onbeforeunload = null;
-	// Save the data from interface into XML and send to destURL
-	// If destURL is null then download XML in client
-	// Now time to render file locally
-	var xmlDoc = interfaceXMLSave();
-	var parent = document.createElement("div");
-	parent.appendChild(xmlDoc);
-	var file = [parent.innerHTML];
-	if (destURL == "local") {
-		var bb = new Blob(file,{type : 'application/xml'});
-		var dnlk = window.URL.createObjectURL(bb);
-		var a = document.createElement("a");
-		a.hidden = '';
-		a.href = dnlk;
-		a.download = "save.xml";
-		a.textContent = "Save File";
-		
-		popup.showPopup();
-		popup.popupContent.innerHTML = "<span>Please save the file below to give to your test supervisor</span><br>";
-		popup.popupContent.appendChild(a);
-	} else {
-		var saveUrlSuffix = "";
-		var saveFilenamePrefix = specification.saveFilenamePrefix;
-		if(typeof(saveFilenamePrefix) === "string" && saveFilenamePrefix.length > 0){
-			saveUrlSuffix  = "&saveFilenamePrefix="+saveFilenamePrefix;
-		}
-		var projectReturn = "";
-		if (typeof specification.projectReturn == "string") {
-			if (specification.projectReturn.substr(0,4) == "http") {
-				projectReturn = specification.projectReturn;
-			}
-		}
-		var saveURL = projectReturn+"php/save.php?key="+storage.SessionKey.key+saveUrlSuffix;
-		var xmlhttp = new XMLHttpRequest;
-		xmlhttp.open("POST", saveURL, true);
-		xmlhttp.setRequestHeader('Content-Type', 'text/xml');
-		xmlhttp.onerror = function(){
-			console.log('Error saving file to server! Presenting download locally');
-			createProjectSave("local");
-		};
-		xmlhttp.onload = function() {
+    // Save the data from interface into XML and send to destURL
+    // If destURL is null then download XML in client
+    // Now time to render file locally
+    var xmlDoc = interfaceXMLSave();
+    var parent = document.createElement("div");
+    parent.appendChild(xmlDoc);
+    var file = [parent.innerHTML];
+    if (destURL == "local") {
+        var bb = new Blob(file, {
+            type: 'application/xml'
+        });
+        var dnlk = window.URL.createObjectURL(bb);
+        var a = document.createElement("a");
+        a.hidden = '';
+        a.href = dnlk;
+        a.download = "save.xml";
+        a.textContent = "Save File";
+
+        popup.showPopup();
+        popup.popupContent.innerHTML = "<span>Please save the file below to give to your test supervisor</span><br>";
+        popup.popupContent.appendChild(a);
+    } else {
+        var saveUrlSuffix = "";
+        var saveFilenamePrefix = specification.saveFilenamePrefix;
+        if (typeof (saveFilenamePrefix) === "string" && saveFilenamePrefix.length > 0) {
+            saveUrlSuffix = "&saveFilenamePrefix=" + saveFilenamePrefix;
+        }
+        var projectReturn = "";
+        if (typeof specification.projectReturn == "string") {
+            if (specification.projectReturn.substr(0, 4) == "http") {
+                projectReturn = specification.projectReturn;
+            }
+        }
+        var saveURL = projectReturn + "php/save.php?key=" + storage.SessionKey.key + saveUrlSuffix;
+        var xmlhttp = new XMLHttpRequest;
+        xmlhttp.open("POST", saveURL, true);
+        xmlhttp.setRequestHeader('Content-Type', 'text/xml');
+        xmlhttp.onerror = function () {
+            console.log('Error saving file to server! Presenting download locally');
+            createProjectSave("local");
+        };
+        xmlhttp.onload = function () {
             console.log(xmlhttp);
             if (this.status >= 300) {
                 console.log("WARNING - Could not update at this time");
@@ -497,239 +492,239 @@
                 if (response.getAttribute("state") == "OK") {
                     window.onbeforeunload = undefined;
                     var file = response.getElementsByTagName("file")[0];
-                    console.log("Save: OK, written "+file.getAttribute("bytes")+"B");
+                    console.log("Save: OK, written " + file.getAttribute("bytes") + "B");
                     if (typeof specification.returnURL == "string" && specification.returnURL.length > 0) {
-                            window.location = specification.returnURL;
+                        window.location = specification.returnURL;
                     } else {
                         popup.popupContent.textContent = specification.exitText;
                     }
                 } else {
                     var message = response.getElementsByTagName("message");
-                    console.log("Save: Error! "+message.textContent);
+                    console.log("Save: Error! " + message.textContent);
                     createProjectSave("local");
                 }
             }
         };
-		xmlhttp.send(file);
-		popup.showPopup();
-		popup.popupContent.innerHTML = null;
-		popup.popupContent.textContent = "Submitting. Please Wait";
-		if(typeof(popup.hideNextButton) === "function"){
-			popup.hideNextButton();
-		}
-		if(typeof(popup.hidePreviousButton) === "function"){
-			popup.hidePreviousButton();
-		}
-	}
+        xmlhttp.send(file);
+        popup.showPopup();
+        popup.popupContent.innerHTML = null;
+        popup.popupContent.textContent = "Submitting. Please Wait";
+        if (typeof (popup.hideNextButton) === "function") {
+            popup.hideNextButton();
+        }
+        if (typeof (popup.hidePreviousButton) === "function") {
+            popup.hidePreviousButton();
+        }
+    }
 }
 
-function errorSessionDump(msg){
-	// Create the partial interface XML save
-	// Include error node with message on why the dump occured
-	popup.showPopup();
-	popup.popupContent.innerHTML = null;
-	var err = document.createElement('error');
-	var parent = document.createElement("div");
-	if (typeof msg === "object")
-	{
-		err.appendChild(msg);
-		popup.popupContent.appendChild(msg);
-		
-	} else {
-		err.textContent = msg;
-		popup.popupContent.innerHTML = "ERROR : "+msg;
-	}
-	var xmlDoc = interfaceXMLSave();
-	xmlDoc.appendChild(err);
-	parent.appendChild(xmlDoc);
-	var file = [parent.innerHTML];
-	var bb = new Blob(file,{type : 'application/xml'});
-	var dnlk = window.URL.createObjectURL(bb);
-	var a = document.createElement("a");
-	a.hidden = '';
-	a.href = dnlk;
-	a.download = "save.xml";
-	a.textContent = "Save File";
-	
-	
-	
-	popup.popupContent.appendChild(a);
+function errorSessionDump(msg) {
+    // Create the partial interface XML save
+    // Include error node with message on why the dump occured
+    popup.showPopup();
+    popup.popupContent.innerHTML = null;
+    var err = document.createElement('error');
+    var parent = document.createElement("div");
+    if (typeof msg === "object") {
+        err.appendChild(msg);
+        popup.popupContent.appendChild(msg);
+
+    } else {
+        err.textContent = msg;
+        popup.popupContent.innerHTML = "ERROR : " + msg;
+    }
+    var xmlDoc = interfaceXMLSave();
+    xmlDoc.appendChild(err);
+    parent.appendChild(xmlDoc);
+    var file = [parent.innerHTML];
+    var bb = new Blob(file, {
+        type: 'application/xml'
+    });
+    var dnlk = window.URL.createObjectURL(bb);
+    var a = document.createElement("a");
+    a.hidden = '';
+    a.href = dnlk;
+    a.download = "save.xml";
+    a.textContent = "Save File";
+
+
+
+    popup.popupContent.appendChild(a);
 }
 
 // Only other global function which must be defined in the interface class. Determines how to create the XML document.
-function interfaceXMLSave(){
-	// Create the XML string to be exported with results
-	return storage.finish();
+function interfaceXMLSave() {
+    // Create the XML string to be exported with results
+    return storage.finish();
 }
 
-function linearToDecibel(gain)
-{
-	return 20.0*Math.log10(gain);
+function linearToDecibel(gain) {
+    return 20.0 * Math.log10(gain);
 }
 
-function decibelToLinear(gain)
-{
-	return Math.pow(10,gain/20.0);
+function decibelToLinear(gain) {
+    return Math.pow(10, gain / 20.0);
 }
 
-function secondsToSamples(time,fs) {
-    return Math.round(time*fs);
+function secondsToSamples(time, fs) {
+    return Math.round(time * fs);
 }
 
-function samplesToSeconds(samples,fs) {
+function samplesToSeconds(samples, fs) {
     return samples / fs;
 }
 
 function randomString(length) {
     var str = ""
-    for (var i=0; i<length; i+=2) {
-        var num = Math.floor(Math.random()*1295);
+    for (var i = 0; i < length; i += 2) {
+        var num = Math.floor(Math.random() * 1295);
         str += num.toString(36);
     }
     return str;
     //return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
 }
 
-function randomiseOrder(input)
-{
-	// This takes an array of information and randomises the order
-	var N = input.length;
-	
-	var inputSequence = []; // For safety purposes: keep track of randomisation
-	for (var counter = 0; counter < N; ++counter) 
-		inputSequence.push(counter) // Fill array
-	var inputSequenceClone = inputSequence.slice(0);
-	
-	var holdArr = [];
-	var outputSequence = [];
-	for (var n=0; n<N; n++)
-	{
-		// First pick a random number
-		var r = Math.random();
-		// Multiply and floor by the number of elements left
-		r = Math.floor(r*input.length);
-		// Pick out that element and delete from the array
-		holdArr.push(input.splice(r,1)[0]);
-		// Do the same with sequence
-		outputSequence.push(inputSequence.splice(r,1)[0]);
-	}
-	console.log(inputSequenceClone.toString()); // print original array to console
-	console.log(outputSequence.toString()); 	// print randomised array to console
-	return holdArr;
+function randomiseOrder(input) {
+    // This takes an array of information and randomises the order
+    var N = input.length;
+
+    var inputSequence = []; // For safety purposes: keep track of randomisation
+    for (var counter = 0; counter < N; ++counter)
+        inputSequence.push(counter) // Fill array
+    var inputSequenceClone = inputSequence.slice(0);
+
+    var holdArr = [];
+    var outputSequence = [];
+    for (var n = 0; n < N; n++) {
+        // First pick a random number
+        var r = Math.random();
+        // Multiply and floor by the number of elements left
+        r = Math.floor(r * input.length);
+        // Pick out that element and delete from the array
+        holdArr.push(input.splice(r, 1)[0]);
+        // Do the same with sequence
+        outputSequence.push(inputSequence.splice(r, 1)[0]);
+    }
+    console.log(inputSequenceClone.toString()); // print original array to console
+    console.log(outputSequence.toString()); // print randomised array to console
+    return holdArr;
 }
 
-function randomSubArray(array,num) {
+function randomSubArray(array, num) {
     if (num > array.length) {
         num = array.length;
     }
     var ret = [];
     while (num > 0) {
         var index = Math.floor(Math.random() * array.length);
-        ret.push( array.splice(index,1)[0] );
+        ret.push(array.splice(index, 1)[0]);
         num--;
     }
     return ret;
 }
 
 function interfacePopup() {
-	// Creates an object to manage the popup
-	this.popup = null;
-	this.popupContent = null;
-	this.popupTitle = null;
-	this.popupResponse = null;
-	this.buttonProceed = null;
-	this.buttonPrevious = null;
-	this.popupOptions = null;
-	this.currentIndex = null;
-	this.node = null;
-	this.store = null;
-	$(window).keypress(function(e){
-			if (e.keyCode == 13 && popup.popup.style.visibility == 'visible')
-			{
-				console.log(e);
-				popup.buttonProceed.onclick();
-				e.preventDefault();
-			}
-		});
-	
-	this.createPopup = function(){
-		// Create popup window interface
-		var insertPoint = document.getElementById("topLevelBody");
-		
-		this.popup = document.getElementById('popupHolder');
-		this.popup.style.left = (window.innerWidth/2)-250 + 'px';
-		this.popup.style.top = (window.innerHeight/2)-125 + 'px';
-		
-		this.popupContent = document.getElementById('popupContent');
-		
-		this.popupTitle = document.getElementById('popupTitle');
-		
-		this.popupResponse = document.getElementById('popupResponse');
-		
-		this.buttonProceed = document.getElementById('popup-proceed');
-		this.buttonProceed.onclick = function(){popup.proceedClicked();};
-		
-		this.buttonPrevious = document.getElementById('popup-previous');
-		this.buttonPrevious.onclick = function(){popup.previousClick();};
-		
+    // Creates an object to manage the popup
+    this.popup = null;
+    this.popupContent = null;
+    this.popupTitle = null;
+    this.popupResponse = null;
+    this.buttonProceed = null;
+    this.buttonPrevious = null;
+    this.popupOptions = null;
+    this.currentIndex = null;
+    this.node = null;
+    this.store = null;
+    $(window).keypress(function (e) {
+        if (e.keyCode == 13 && popup.popup.style.visibility == 'visible') {
+            console.log(e);
+            popup.buttonProceed.onclick();
+            e.preventDefault();
+        }
+    });
+
+    this.createPopup = function () {
+        // Create popup window interface
+        var insertPoint = document.getElementById("topLevelBody");
+
+        this.popup = document.getElementById('popupHolder');
+        this.popup.style.left = (window.innerWidth / 2) - 250 + 'px';
+        this.popup.style.top = (window.innerHeight / 2) - 125 + 'px';
+
+        this.popupContent = document.getElementById('popupContent');
+
+        this.popupTitle = document.getElementById('popupTitle');
+
+        this.popupResponse = document.getElementById('popupResponse');
+
+        this.buttonProceed = document.getElementById('popup-proceed');
+        this.buttonProceed.onclick = function () {
+            popup.proceedClicked();
+        };
+
+        this.buttonPrevious = document.getElementById('popup-previous');
+        this.buttonPrevious.onclick = function () {
+            popup.previousClick();
+        };
+
         this.hidePopup();
-		this.popup.style.visibility = 'hidden';
-	};
-	
-	this.showPopup = function(){
-		if (this.popup == null) {
-			this.createPopup();
-		}
-		this.popup.style.visibility = 'visible';
-		var blank = document.getElementsByClassName('testHalt')[0];
-		blank.style.visibility = 'visible';
-        this.popupResponse.style.left="0%";
-	};
-	
-	this.hidePopup = function(){
+        this.popup.style.visibility = 'hidden';
+    };
+
+    this.showPopup = function () {
+        if (this.popup == null) {
+            this.createPopup();
+        }
+        this.popup.style.visibility = 'visible';
+        var blank = document.getElementsByClassName('testHalt')[0];
+        blank.style.visibility = 'visible';
+        this.popupResponse.style.left = "0%";
+    };
+
+    this.hidePopup = function () {
         if (this.popup) {
             this.popup.style.visibility = 'hidden';
             var blank = document.getElementsByClassName('testHalt')[0];
             blank.style.visibility = 'hidden';
             this.buttonPrevious.style.visibility = 'inherit';
         }
-	};
-	
-	this.postNode = function() {
-		// This will take the node from the popupOptions and display it
-		var node = this.popupOptions[this.currentIndex];
-		this.popupResponse.innerHTML = "";
-		this.popupTitle.textContent = node.specification.statement;
-		if (node.specification.type == 'question') {
-			var textArea = document.createElement('textarea');
-			switch (node.specification.boxsize) {
-			case 'small':
-				textArea.cols = "20";
-				textArea.rows = "1";
-				break;
-			case 'normal':
-				textArea.cols = "30";
-				textArea.rows = "2";
-				break;
-			case 'large':
-				textArea.cols = "40";
-				textArea.rows = "5";
-				break;
-			case 'huge':
-				textArea.cols = "50";
-				textArea.rows = "10";
-				break;
-			}
+    };
+
+    this.postNode = function () {
+        // This will take the node from the popupOptions and display it
+        var node = this.popupOptions[this.currentIndex];
+        this.popupResponse.innerHTML = "";
+        this.popupTitle.textContent = node.specification.statement;
+        if (node.specification.type == 'question') {
+            var textArea = document.createElement('textarea');
+            switch (node.specification.boxsize) {
+                case 'small':
+                    textArea.cols = "20";
+                    textArea.rows = "1";
+                    break;
+                case 'normal':
+                    textArea.cols = "30";
+                    textArea.rows = "2";
+                    break;
+                case 'large':
+                    textArea.cols = "40";
+                    textArea.rows = "5";
+                    break;
+                case 'huge':
+                    textArea.cols = "50";
+                    textArea.rows = "10";
+                    break;
+            }
             if (node.response == undefined) {
                 node.response = "";
             } else {
                 textArea.value = node.response;
             }
-			this.popupResponse.appendChild(textArea);
-			textArea.focus();
-            this.popupResponse.style.textAlign="center";
-            this.popupResponse.style.left="0%";
-		} else if (node.specification.type == 'checkbox') {
+            this.popupResponse.appendChild(textArea);
+            textArea.focus();
+            this.popupResponse.style.textAlign = "center";
+            this.popupResponse.style.left = "0%";
+        } else if (node.specification.type == 'checkbox') {
             if (node.response == undefined) {
                 node.response = Array(node.specification.options.length);
             }
@@ -737,25 +732,25 @@
             var table = document.createElement("table");
             table.className = "popup-option-list";
             table.border = "0";
-			for (var option of node.specification.options) {
+            for (var option of node.specification.options) {
                 var tr = document.createElement("tr");
                 table.appendChild(tr);
                 var td = document.createElement("td");
                 tr.appendChild(td);
                 var input = document.createElement('input');
                 input.id = option.name;
-				input.type = 'checkbox';
+                input.type = 'checkbox';
                 td.appendChild(input);
-                
+
                 td = document.createElement("td");
                 tr.appendChild(td);
-				var span = document.createElement('span');
-				span.textContent = option.text;
+                var span = document.createElement('span');
+                span.textContent = option.text;
                 td.appendChild(span);
-				var tr = document.createElement('div');
-				tr.setAttribute('name','option');
+                var tr = document.createElement('div');
+                tr.setAttribute('name', 'option');
                 tr.className = "popup-option-checbox";
-                if (node.response[index] != undefined){
+                if (node.response[index] != undefined) {
                     if (node.response[index].checked == true) {
                         input.checked = "true";
                     }
@@ -763,34 +758,37 @@
                 index++;
             }
             this.popupResponse.appendChild(table);
-		} else if (node.specification.type == 'radio') {
+        } else if (node.specification.type == 'radio') {
             if (node.response == undefined) {
-                node.response = {name: "", text: ""};
+                node.response = {
+                    name: "",
+                    text: ""
+                };
             }
             var index = 0;
-			var table = document.createElement("table");
+            var table = document.createElement("table");
             table.className = "popup-option-list";
             table.border = "0";
-			for (var option of node.specification.options) {
+            for (var option of node.specification.options) {
                 var tr = document.createElement("tr");
                 table.appendChild(tr);
                 var td = document.createElement("td");
                 tr.appendChild(td);
                 var input = document.createElement('input');
                 input.id = option.name;
-				input.type = 'radio';
+                input.type = 'radio';
                 input.name = node.specification.id;
                 td.appendChild(input);
-                
+
                 td = document.createElement("td");
                 tr.appendChild(td);
-				var span = document.createElement('span');
-				span.textContent = option.text;
+                var span = document.createElement('span');
+                span.textContent = option.text;
                 td.appendChild(span);
-				var tr = document.createElement('div');
-				tr.setAttribute('name','option');
+                var tr = document.createElement('div');
+                tr.setAttribute('name', 'option');
                 tr.className = "popup-option-checbox";
-                if (node.response[index] != undefined){
+                if (node.response[index] != undefined) {
                     if (node.response[index].checked == true) {
                         input.checked = "true";
                     }
@@ -798,19 +796,25 @@
                 index++;
             }
             this.popupResponse.appendChild(table);
-		} else if (node.specification.type == 'number') {
-			var input = document.createElement('input');
-			input.type = 'textarea';
-			if (node.min != null) {input.min = node.specification.min;}
-			if (node.max != null) {input.max = node.specification.max;}
-			if (node.step != null) {input.step = node.specification.step;}
+        } else if (node.specification.type == 'number') {
+            var input = document.createElement('input');
+            input.type = 'textarea';
+            if (node.min != null) {
+                input.min = node.specification.min;
+            }
+            if (node.max != null) {
+                input.max = node.specification.max;
+            }
+            if (node.step != null) {
+                input.step = node.specification.step;
+            }
             if (node.response != undefined) {
                 input.value = node.response;
             }
-			this.popupResponse.appendChild(input);
-            this.popupResponse.style.textAlign="center";
-            this.popupResponse.style.left="0%";
-		} else if (node.specification.type == "video") {
+            this.popupResponse.appendChild(input);
+            this.popupResponse.style.textAlign = "center";
+            this.popupResponse.style.left = "0%";
+        } else if (node.specification.type == "video") {
             var video = document.createElement("video");
             video.src = node.specification.url;
             this.popupResponse.appendChild(video);
@@ -820,67 +824,66 @@
             iframe.src = node.specification.url;
             this.popupResponse.appendChild(iframe);
         }
-		if(this.currentIndex+1 == this.popupOptions.length) {
-			if (this.node.location == "pre") {
-				this.buttonProceed.textContent = 'Start';
-			} else {
-				this.buttonProceed.textContent = 'Submit';
-			}
-		} else {
-			this.buttonProceed.textContent = 'Next';
-		}
-		if(this.currentIndex > 0)
-			this.buttonPrevious.style.visibility = 'visible';
-		else
-			this.buttonPrevious.style.visibility = 'hidden';
-	};
-	
-	this.initState = function(node,store) {
-		//Call this with your preTest and postTest nodes when needed to
-		// initialise the popup procedure.
-		if (node.options.length > 0) {
-			this.popupOptions = [];
-			this.node = node;
-			this.store = store;
-			for (var opt of node.options)
-			{
-				this.popupOptions.push({
-					specification: opt,
-					response: null
-				});
-			}			
-			this.currentIndex = 0;
-			this.showPopup();
-			this.postNode();
-		} else {
-			advanceState();
-		}
-	};
-	
-	this.proceedClicked = function() {
-		// Each time the popup button is clicked!
+        if (this.currentIndex + 1 == this.popupOptions.length) {
+            if (this.node.location == "pre") {
+                this.buttonProceed.textContent = 'Start';
+            } else {
+                this.buttonProceed.textContent = 'Submit';
+            }
+        } else {
+            this.buttonProceed.textContent = 'Next';
+        }
+        if (this.currentIndex > 0)
+            this.buttonPrevious.style.visibility = 'visible';
+        else
+            this.buttonPrevious.style.visibility = 'hidden';
+    };
+
+    this.initState = function (node, store) {
+        //Call this with your preTest and postTest nodes when needed to
+        // initialise the popup procedure.
+        if (node.options.length > 0) {
+            this.popupOptions = [];
+            this.node = node;
+            this.store = store;
+            for (var opt of node.options) {
+                this.popupOptions.push({
+                    specification: opt,
+                    response: null
+                });
+            }
+            this.currentIndex = 0;
+            this.showPopup();
+            this.postNode();
+        } else {
+            advanceState();
+        }
+    };
+
+    this.proceedClicked = function () {
+        // Each time the popup button is clicked!
         if (testState.stateIndex == 0 && specification.calibration) {
             interfaceContext.calibrationModuleObject.collect();
             advanceState();
             return;
         }
-		var node = this.popupOptions[this.currentIndex];
-		if (node.specification.type == 'question') {
-			// Must extract the question data
-			var textArea = $(popup.popupContent).find('textarea')[0];
-			if (node.specification.mandatory == true && textArea.value.length == 0) {
-                interfaceContext.lightbox.post("Error","This question is mandatory");
-				return;
-			} else {
-				// Save the text content
-				console.log("Question: "+ node.specification.statement);
-				console.log("Question Response: "+ textArea.value);
-				node.response = textArea.value;
-			}
+        var node = this.popupOptions[this.currentIndex];
+        if (node.specification.type == 'question') {
+            // Must extract the question data
+            var textArea = $(popup.popupContent).find('textarea')[0];
+            if (node.specification.mandatory == true && textArea.value.length == 0) {
+                interfaceContext.lightbox.post("Error", "This question is mandatory");
+                return;
+            } else {
+                // Save the text content
+                console.log("Question: " + node.specification.statement);
+                console.log("Question Response: " + textArea.value);
+                node.response = textArea.value;
+            }
             // Perform the conditional
             for (var condition of node.specification.conditions) {
                 var pass = false;
-                switch(condition.check) {
+                switch (condition.check) {
                     case "equals":
                         if (textArea.value == condition.value) {
                             pass = true;
@@ -903,30 +906,34 @@
                     jumpID = condition.jumpToOnFail;
                 }
                 if (jumpID != undefined) {
-                    var index = this.popupOptions.findIndex(function(item,index,element){
-                        if (item.specification.id == jumpID) {return true;} else {return false;}
-                    },this);
-                    this.currentIndex = index-1;
+                    var index = this.popupOptions.findIndex(function (item, index, element) {
+                        if (item.specification.id == jumpID) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }, this);
+                    this.currentIndex = index - 1;
                     break;
                 }
             }
-		} else if (node.specification.type == 'checkbox') {
-			// Must extract checkbox data
-			console.log("Checkbox: "+ node.specification.statement);
-			var inputs = this.popupResponse.getElementsByTagName('input');
-			node.response = [];
-			for (var i=0; i<node.specification.options.length; i++) {
-				node.response.push({
-					name: node.specification.options[i].name,
-					text: node.specification.options[i].text,
-					checked: inputs[i].checked
-				});
-				console.log(node.specification.options[i].name+": "+ inputs[i].checked);
-			}
+        } else if (node.specification.type == 'checkbox') {
+            // Must extract checkbox data
+            console.log("Checkbox: " + node.specification.statement);
+            var inputs = this.popupResponse.getElementsByTagName('input');
+            node.response = [];
+            for (var i = 0; i < node.specification.options.length; i++) {
+                node.response.push({
+                    name: node.specification.options[i].name,
+                    text: node.specification.options[i].text,
+                    checked: inputs[i].checked
+                });
+                console.log(node.specification.options[i].name + ": " + inputs[i].checked);
+            }
             // Perform the conditional
             for (var condition of node.specification.conditions) {
                 var pass = false;
-                switch(condition.check) {
+                switch (condition.check) {
                     case "equals":
                     case "greaterThan":
                     case "lessThan":
@@ -948,39 +955,41 @@
                     jumpID = condition.jumpToOnFail;
                 }
                 if (jumpID != undefined) {
-                    var index = this.popupOptions.findIndex(function(item,index,element){
-                        if (item.specification.id == jumpID) {return true;} else {return false;}
-                    },this);
-                    this.currentIndex = index-1;
+                    var index = this.popupOptions.findIndex(function (item, index, element) {
+                        if (item.specification.id == jumpID) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }, this);
+                    this.currentIndex = index - 1;
                     break;
                 }
             }
-		} else if (node.specification.type == "radio") {
-			var optHold = this.popupResponse;
-			console.log("Radio: "+ node.specification.statement);
-			node.response = null;
-			var i=0;
-			var inputs = optHold.getElementsByTagName('input');
-			while(node.response == null) {
-				if (i == inputs.length)
-				{
-					if (node.specification.mandatory == true)
-					{
-                        interfaceContext.lightbox.post("Error","Please select one option");
+        } else if (node.specification.type == "radio") {
+            var optHold = this.popupResponse;
+            console.log("Radio: " + node.specification.statement);
+            node.response = null;
+            var i = 0;
+            var inputs = optHold.getElementsByTagName('input');
+            while (node.response == null) {
+                if (i == inputs.length) {
+                    if (node.specification.mandatory == true) {
+                        interfaceContext.lightbox.post("Error", "Please select one option");
                         return;
-					}
+                    }
                     break;
-				}
-				if (inputs[i].checked == true) {
-					node.response = node.specification.options[i];
-					console.log("Selected: "+ node.specification.options[i].name);
-				}
-				i++;
-			}
+                }
+                if (inputs[i].checked == true) {
+                    node.response = node.specification.options[i];
+                    console.log("Selected: " + node.specification.options[i].name);
+                }
+                i++;
+            }
             // Perform the conditional
             for (var condition of node.specification.conditions) {
                 var pass = false;
-                switch(condition.check) {
+                switch (condition.check) {
                     case "contains":
                     case "greaterThan":
                     case "lessThan":
@@ -999,37 +1008,41 @@
                     jumpID = condition.jumpToOnFail;
                 }
                 if (jumpID != undefined) {
-                    var index = this.popupOptions.findIndex(function(item,index,element){
-                        if (item.specification.id == jumpID) {return true;} else {return false;}
-                    },this);
-                    this.currentIndex = index-1;
+                    var index = this.popupOptions.findIndex(function (item, index, element) {
+                        if (item.specification.id == jumpID) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }, this);
+                    this.currentIndex = index - 1;
                     break;
                 }
             }
-		} else if (node.specification.type == "number") {
-			var input = this.popupContent.getElementsByTagName('input')[0];
-			if (node.mandatory == true && input.value.length == 0) {
-				interfaceContext.lightbox.post("Error",'This question is mandatory. Please enter a number');
-				return;
-			}
-			var enteredNumber = Number(input.value);
-			if (isNaN(enteredNumber)) {
-				interfaceContext.lightbox.post("Error",'Please enter a valid number');
-				return;
-			}
-			if (enteredNumber < node.min && node.min != null) {
-				interfaceContext.lightbox.post("Error",'Number is below the minimum value of '+node.min);
-				return;
-			}
-			if (enteredNumber > node.max && node.max != null) {
-				interfaceContext.lightbox.post("Error",'Number is above the maximum value of '+node.max);
-				return;
-			}
-			node.response = input.value;
+        } else if (node.specification.type == "number") {
+            var input = this.popupContent.getElementsByTagName('input')[0];
+            if (node.mandatory == true && input.value.length == 0) {
+                interfaceContext.lightbox.post("Error", 'This question is mandatory. Please enter a number');
+                return;
+            }
+            var enteredNumber = Number(input.value);
+            if (isNaN(enteredNumber)) {
+                interfaceContext.lightbox.post("Error", 'Please enter a valid number');
+                return;
+            }
+            if (enteredNumber < node.min && node.min != null) {
+                interfaceContext.lightbox.post("Error", 'Number is below the minimum value of ' + node.min);
+                return;
+            }
+            if (enteredNumber > node.max && node.max != null) {
+                interfaceContext.lightbox.post("Error", 'Number is above the maximum value of ' + node.max);
+                return;
+            }
+            node.response = input.value;
             // Perform the conditional
             for (var condition of node.specification.conditions) {
                 var pass = false;
-                switch(condition.check) {
+                switch (condition.check) {
                     case "contains":
                         console.log("Survey Element of type 'number' cannot interpret contains conditions. IGNORING");
                         break;
@@ -1056,93 +1069,93 @@
                     jumpID = condition.jumpToOnFail;
                 }
                 if (jumpID != undefined) {
-                    var index = this.popupOptions.findIndex(function(item,index,element){
-                        if (item.specification.id == jumpID) {return true;} else {return false;}
-                    },this);
-                    this.currentIndex = index-1;
+                    var index = this.popupOptions.findIndex(function (item, index, element) {
+                        if (item.specification.id == jumpID) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }, this);
+                    this.currentIndex = index - 1;
                     break;
                 }
             }
-		}
-		this.currentIndex++;
-		if (this.currentIndex < this.popupOptions.length) {
-			this.postNode();
-		} else {
-			// Reached the end of the popupOptions
-            this.popupContent.innerHTML = "";
-			this.hidePopup();
-			for (var node of this.popupOptions)
-			{
-				this.store.postResult(node);
-			}
+        }
+        this.currentIndex++;
+        if (this.currentIndex < this.popupOptions.length) {
+            this.postNode();
+        } else {
+            // Reached the end of the popupOptions
+            this.popupTitle.textContent = "";
+            this.popupResponse.innerHTML = "";
+            this.hidePopup();
+            for (var node of this.popupOptions) {
+                this.store.postResult(node);
+            }
             this.store.complete();
-			advanceState();
-		}
-	};
-	
-	this.previousClick = function() {
-		// Triggered when the 'Back' button is clicked in the survey
-		if (this.currentIndex > 0) {
-			this.currentIndex--;
-			this.postNode();
-		}
-	};
-	
-	this.resize = function(event)
-	{
-		// Called on window resize;
-		if (this.popup != null) {
-			this.popup.style.left = (window.innerWidth/2)-250 + 'px';
-			this.popup.style.top = (window.innerHeight/2)-125 + 'px';
-			var blank = document.getElementsByClassName('testHalt')[0];
-			blank.style.width = window.innerWidth;
-			blank.style.height = window.innerHeight;
-		}
-	};
-    this.hideNextButton = function() {
+            advanceState();
+        }
+    };
+
+    this.previousClick = function () {
+        // Triggered when the 'Back' button is clicked in the survey
+        if (this.currentIndex > 0) {
+            this.currentIndex--;
+            this.postNode();
+        }
+    };
+
+    this.resize = function (event) {
+        // Called on window resize;
+        if (this.popup != null) {
+            this.popup.style.left = (window.innerWidth / 2) - 250 + 'px';
+            this.popup.style.top = (window.innerHeight / 2) - 125 + 'px';
+            var blank = document.getElementsByClassName('testHalt')[0];
+            blank.style.width = window.innerWidth;
+            blank.style.height = window.innerHeight;
+        }
+    };
+    this.hideNextButton = function () {
         this.buttonProceed.style.visibility = "hidden";
     }
-    this.hidePreviousButton = function() {
+    this.hidePreviousButton = function () {
         this.buttonPrevious.style.visibility = "hidden";
     }
-    this.showNextButton = function() {
+    this.showNextButton = function () {
         this.buttonProceed.style.visibility = "visible";
     }
-    this.showPreviousButton = function() {
+    this.showPreviousButton = function () {
         this.buttonPrevious.style.visibility = "visible";
     }
 }
 
-function advanceState()
-{
-	// Just for complete clarity
-	testState.advanceState();
+function advanceState() {
+    // Just for complete clarity
+    testState.advanceState();
 }
 
-function stateMachine()
-{
-	// Object prototype for tracking and managing the test state
-	this.stateMap = [];
-	this.preTestSurvey = null;
-	this.postTestSurvey = null;
-	this.stateIndex = null;
-	this.currentStateMap = null;
-	this.currentStatePosition = null;
+function stateMachine() {
+    // Object prototype for tracking and managing the test state
+    this.stateMap = [];
+    this.preTestSurvey = null;
+    this.postTestSurvey = null;
+    this.stateIndex = null;
+    this.currentStateMap = null;
+    this.currentStatePosition = null;
     this.currentStore = null;
-	this.initialise = function(){
-        
-		// Get the data from Specification
-		var pagePool = [];
+    this.initialise = function () {
+
+        // Get the data from Specification
+        var pagePool = [];
         var pageInclude = [];
-		for (var page of specification.pages)
-		{
+        for (var page of specification.pages) {
             if (page.alwaysInclude) {
                 pageInclude.push(page);
             } else {
                 pagePool.push(page);
             }
-		}
-        
+        }
+
         // Find how many are left to get
         var numPages = specification.poolSize;
         if (numPages > pagePool.length) {
@@ -1153,29 +1166,27 @@
             numPages = specification.pages.length;
         }
         numPages -= pageInclude.length;
-        
+
         if (numPages > 0) {
             // Go find the rest of the pages from the pool
             var subarr = null;
             if (specification.randomiseOrder) {
                 // Append a random sub-array
-                subarr = randomSubArray(pagePool,numPages);
+                subarr = randomSubArray(pagePool, numPages);
             } else {
                 // Append the matching number
-                subarr = pagePool.slice(0,numPages);
+                subarr = pagePool.slice(0, numPages);
             }
             pageInclude = pageInclude.concat(subarr);
         }
-        
+
         // We now have our selected pages in pageInclude array
-		if (specification.randomiseOrder)
-		{
-			pageInclude = randomiseOrder(pageInclude);
-		}
-		for (var i=0; i<pageInclude.length; i++)
-		{
+        if (specification.randomiseOrder) {
+            pageInclude = randomiseOrder(pageInclude);
+        }
+        for (var i = 0; i < pageInclude.length; i++) {
             pageInclude[i].presentedId = i;
-			this.stateMap.push(pageInclude[i]);
+            this.stateMap.push(pageInclude[i]);
             // For each selected page, we must get the sub pool
             if (pageInclude[i].poolSize != 0 && pageInclude[i].poolSize != pageInclude[i].audioElements.length) {
                 var elemInclude = [];
@@ -1188,41 +1199,44 @@
                     }
                 }
                 var numElems = pageInclude[i].poolSize - elemInclude.length;
-                pageInclude[i].audioElements = elemInclude.concat(randomSubArray(elemPool,numElems));
+                pageInclude[i].audioElements = elemInclude.concat(randomSubArray(elemPool, numElems));
             }
             storage.createTestPageStore(pageInclude[i]);
             audioEngineContext.loadPageData(pageInclude[i]);
-		}
-        
-		if (specification.preTest != null) {this.preTestSurvey = specification.preTest;}
-		if (specification.postTest != null) {this.postTestSurvey = specification.postTest;}
-		
-		if (this.stateMap.length > 0) {
-			if(this.stateIndex != null) {
-				console.log('NOTE - State already initialise');
-			}
-			this.stateIndex = -2;
+        }
+
+        if (specification.preTest != null) {
+            this.preTestSurvey = specification.preTest;
+        }
+        if (specification.postTest != null) {
+            this.postTestSurvey = specification.postTest;
+        }
+
+        if (this.stateMap.length > 0) {
+            if (this.stateIndex != null) {
+                console.log('NOTE - State already initialise');
+            }
+            this.stateIndex = -2;
             console.log('Starting test...');
-		} else {
-			console.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP');
-		}
-	};
-	this.advanceState = function(){
-		if (this.stateIndex == null) {
-			this.initialise();
-		}
+        } else {
+            console.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP');
+        }
+    };
+    this.advanceState = function () {
+        if (this.stateIndex == null) {
+            this.initialise();
+        }
         if (this.stateIndex > -2) {
             storage.update();
         }
-		if (this.stateIndex == -2) {
+        if (this.stateIndex == -2) {
             this.stateIndex++;
-			if (this.preTestSurvey != null)
-			{
-				popup.initState(this.preTestSurvey,storage.globalPreTest);
-			} else {
-				this.advanceState();
-			}
-		} else if (this.stateIndex == -1) {
+            if (this.preTestSurvey != null) {
+                popup.initState(this.preTestSurvey, storage.globalPreTest);
+            } else {
+                this.advanceState();
+            }
+        } else if (this.stateIndex == -1) {
             this.stateIndex++;
             if (specification.calibration) {
                 popup.showPopup();
@@ -1233,119 +1247,105 @@
             } else {
                 this.advanceState();
             }
-        } 
-        else if (this.stateIndex == this.stateMap.length)
-		{
-			// All test pages complete, post test
-			console.log('Ending test ...');
-			this.stateIndex++;
-			if (this.postTestSurvey == null) {
-				this.advanceState();
-			} else {
-				popup.initState(this.postTestSurvey,storage.globalPostTest);
-			}
-		} else if (this.stateIndex > this.stateMap.length)
-		{
-			createProjectSave(specification.projectReturn);
-		}
-		else
-		{
+        } else if (this.stateIndex == this.stateMap.length) {
+            // All test pages complete, post test
+            console.log('Ending test ...');
+            this.stateIndex++;
+            if (this.postTestSurvey == null) {
+                this.advanceState();
+            } else {
+                popup.initState(this.postTestSurvey, storage.globalPostTest);
+            }
+        } else if (this.stateIndex > this.stateMap.length) {
+            createProjectSave(specification.projectReturn);
+        } else {
             popup.hidePopup();
-			if (this.currentStateMap == null)
-			{
-				this.currentStateMap = this.stateMap[this.stateIndex];
+            if (this.currentStateMap == null) {
+                this.currentStateMap = this.stateMap[this.stateIndex];
                 // Find and extract the outside reference
-                var elements = [], ref = [];
+                var elements = [],
+                    ref = [];
                 var elem;
-                while(elem = this.currentStateMap.audioElements.pop())
-                {
+                while (elem = this.currentStateMap.audioElements.pop()) {
                     if (elem.type == "outside-reference") {
                         ref.push(elem);
-                    }
-                    else {
+                    } else {
                         elements.push(elem);
                     }
                 }
                 elements = elements.reverse();
-				if (this.currentStateMap.randomiseOrder)
-				{
-					elements = randomiseOrder(elements);
-				}
+                if (this.currentStateMap.randomiseOrder) {
+                    elements = randomiseOrder(elements);
+                }
                 this.currentStateMap.audioElements = elements.concat(ref);
-                
+
                 this.currentStore = storage.testPages[this.stateIndex];
-				if (this.currentStateMap.preTest != null)
-				{
-					this.currentStatePosition = 'pre';
-					popup.initState(this.currentStateMap.preTest,storage.testPages[this.stateIndex].preTest);
-				} else {
-					this.currentStatePosition = 'test';
-				}
-				interfaceContext.newPage(this.currentStateMap,storage.testPages[this.stateIndex]);
-				return;
-			}
-			switch(this.currentStatePosition)
-			{
-			case 'pre':
-				this.currentStatePosition = 'test';
-				break;
-			case 'test':
-				this.currentStatePosition = 'post';
-				// Save the data
-				this.testPageCompleted();
-				if (this.currentStateMap.postTest == null)
-				{
-					this.advanceState();
-					return;
-				} else {
-					popup.initState(this.currentStateMap.postTest,storage.testPages[this.stateIndex].postTest);
-				}
-				break;
-			case 'post':
-				this.stateIndex++;
-				this.currentStateMap = null;
-				this.advanceState();
-				break;
-			};
-		}
-	};
-	
-	this.testPageCompleted = function() {
-		// Function called each time a test page has been completed
-		var storePoint = storage.testPages[this.stateIndex];
-		// First get the test metric
-		
-		var metric = storePoint.XMLDOM.getElementsByTagName('metric')[0];
-		if (audioEngineContext.metric.enableTestTimer)
-		{
-			var testTime = storePoint.parent.document.createElement('metricresult');
-			testTime.id = 'testTime';
-			testTime.textContent = audioEngineContext.timer.testDuration;
-			metric.appendChild(testTime);
-		}
-		
-		var audioObjects = audioEngineContext.audioObjects;
-		for (var ao of audioEngineContext.audioObjects) 
-		{
-			ao.exportXMLDOM();
-		}
-		for (var element of interfaceContext.commentQuestions)
-		{
-			element.exportXMLDOM(storePoint);
-		}
-		pageXMLSave(storePoint.XMLDOM, this.currentStateMap);
+                if (this.currentStateMap.preTest != null) {
+                    this.currentStatePosition = 'pre';
+                    popup.initState(this.currentStateMap.preTest, storage.testPages[this.stateIndex].preTest);
+                } else {
+                    this.currentStatePosition = 'test';
+                }
+                interfaceContext.newPage(this.currentStateMap, storage.testPages[this.stateIndex]);
+                return;
+            }
+            switch (this.currentStatePosition) {
+                case 'pre':
+                    this.currentStatePosition = 'test';
+                    break;
+                case 'test':
+                    this.currentStatePosition = 'post';
+                    // Save the data
+                    this.testPageCompleted();
+                    if (this.currentStateMap.postTest == null) {
+                        this.advanceState();
+                        return;
+                    } else {
+                        popup.initState(this.currentStateMap.postTest, storage.testPages[this.stateIndex].postTest);
+                    }
+                    break;
+                case 'post':
+                    this.stateIndex++;
+                    this.currentStateMap = null;
+                    this.advanceState();
+                    break;
+            };
+        }
+    };
+
+    this.testPageCompleted = function () {
+        // Function called each time a test page has been completed
+        var storePoint = storage.testPages[this.stateIndex];
+        // First get the test metric
+
+        var metric = storePoint.XMLDOM.getElementsByTagName('metric')[0];
+        if (audioEngineContext.metric.enableTestTimer) {
+            var testTime = storePoint.parent.document.createElement('metricresult');
+            testTime.id = 'testTime';
+            testTime.textContent = audioEngineContext.timer.testDuration;
+            metric.appendChild(testTime);
+        }
+
+        var audioObjects = audioEngineContext.audioObjects;
+        for (var ao of audioEngineContext.audioObjects) {
+            ao.exportXMLDOM();
+        }
+        for (var element of interfaceContext.commentQuestions) {
+            element.exportXMLDOM(storePoint);
+        }
+        pageXMLSave(storePoint.XMLDOM, this.currentStateMap);
         storePoint.complete();
-	};
-    
-    this.getCurrentTestPage = function() {
-        if (this.stateIndex >= 0 && this.stateIndex< this.stateMap.length) {
+    };
+
+    this.getCurrentTestPage = function () {
+        if (this.stateIndex >= 0 && this.stateIndex < this.stateMap.length) {
             return this.currentStateMap;
         } else {
             return null;
         }
     }
-    this.getCurrentTestPageStore = function() {
-        if (this.stateIndex >= 0 && this.stateIndex< this.stateMap.length) {
+    this.getCurrentTestPageStore = function () {
+        if (this.stateIndex >= 0 && this.stateIndex < this.stateMap.length) {
             return this.currentStore;
         } else {
             return null;
@@ -1354,172 +1354,162 @@
 }
 
 function AudioEngine(specification) {
-	
-	// Create two output paths, the main outputGain and fooGain.
-	// Output gain is default to 1 and any items for playback route here
-	// Foo gain is used for analysis to ensure paths get processed, but are not heard
-	// because web audio will optimise and any route which does not go to the destination gets ignored.
-	this.outputGain = audioContext.createGain();
-	this.fooGain = audioContext.createGain();
-	this.fooGain.gain = 0;
-	
-	// Use this to detect playback state: 0 - stopped, 1 - playing
-	this.status = 0;
-	
-	// Connect both gains to output
-	this.outputGain.connect(audioContext.destination);
-	this.fooGain.connect(audioContext.destination);
-	
-	// Create the timer Object
-	this.timer = new timer();
-	// Create session metrics
-	this.metric = new sessionMetrics(this,specification);
-	
-	this.loopPlayback = false;
+
+    // Create two output paths, the main outputGain and fooGain.
+    // Output gain is default to 1 and any items for playback route here
+    // Foo gain is used for analysis to ensure paths get processed, but are not heard
+    // because web audio will optimise and any route which does not go to the destination gets ignored.
+    this.outputGain = audioContext.createGain();
+    this.fooGain = audioContext.createGain();
+    this.fooGain.gain = 0;
+
+    // Use this to detect playback state: 0 - stopped, 1 - playing
+    this.status = 0;
+
+    // Connect both gains to output
+    this.outputGain.connect(audioContext.destination);
+    this.fooGain.connect(audioContext.destination);
+
+    // Create the timer Object
+    this.timer = new timer();
+    // Create session metrics
+    this.metric = new sessionMetrics(this, specification);
+
+    this.loopPlayback = false;
     this.synchPlayback = false;
     this.pageSpecification = null;
-	
-	this.pageStore = null;
-	
-	// Create store for new audioObjects
-	this.audioObjects = [];
-	
-	this.buffers = [];
-	this.bufferObj = function()
-	{
-		this.url = null;
-		this.buffer = null;
-		this.xmlRequest = new XMLHttpRequest();
-		this.xmlRequest.parent = this;
-		this.users = [];
+
+    this.pageStore = null;
+
+    // Create store for new audioObjects
+    this.audioObjects = [];
+
+    this.buffers = [];
+    this.bufferObj = function () {
+        this.url = null;
+        this.buffer = null;
+        this.xmlRequest = new XMLHttpRequest();
+        this.xmlRequest.parent = this;
+        this.users = [];
         this.progress = 0;
         this.status = 0;
-		this.ready = function()
-		{
-            if (this.status >= 2)
-            {
+        this.ready = function () {
+            if (this.status >= 2) {
                 this.status = 3;
             }
-			for (var i=0; i<this.users.length; i++)
-			{
-				this.users[i].state = 1;
-				if (this.users[i].interfaceDOM != null)
-				{
-					this.users[i].bufferLoaded(this);
-				}
-			}
-		};
-		this.getMedia = function(url) {
-			this.url = url;
-			this.xmlRequest.open('GET',this.url,true);
-			this.xmlRequest.responseType = 'arraybuffer';
-			
-			var bufferObj = this;
-			
-			// Create callback to decode the data asynchronously
-			this.xmlRequest.onloadend = function() {
+            for (var i = 0; i < this.users.length; i++) {
+                this.users[i].state = 1;
+                if (this.users[i].interfaceDOM != null) {
+                    this.users[i].bufferLoaded(this);
+                }
+            }
+        };
+        this.getMedia = function (url) {
+            this.url = url;
+            this.xmlRequest.open('GET', this.url, true);
+            this.xmlRequest.responseType = 'arraybuffer';
+
+            var bufferObj = this;
+
+            // Create callback to decode the data asynchronously
+            this.xmlRequest.onloadend = function () {
                 // Use inbuilt WAVE decoder first
-                if (this.status == -1) {return;}
+                if (this.status == -1) {
+                    return;
+                }
                 var waveObj = new WAVE();
-                audioContext.decodeAudioData(bufferObj.xmlRequest.response, function(decodedData) {
-                        bufferObj.buffer = decodedData;
-                        bufferObj.status = 2;
-                        calculateLoudness(bufferObj,"I");
-                }, function(e) {
+                audioContext.decodeAudioData(bufferObj.xmlRequest.response, function (decodedData) {
+                    bufferObj.buffer = decodedData;
+                    bufferObj.status = 2;
+                    calculateLoudness(bufferObj, "I");
+                }, function (e) {
                     var waveObj = new WAVE();
-                    if (waveObj.open(bufferObj.xmlRequest.response) == 0)
-                    {
-                        bufferObj.buffer = audioContext.createBuffer(waveObj.num_channels,waveObj.num_samples,waveObj.sample_rate);
-                        for (var c=0; c<waveObj.num_channels; c++)
-                        {
+                    if (waveObj.open(bufferObj.xmlRequest.response) == 0) {
+                        bufferObj.buffer = audioContext.createBuffer(waveObj.num_channels, waveObj.num_samples, waveObj.sample_rate);
+                        for (var c = 0; c < waveObj.num_channels; c++) {
                             var buffer_ptr = bufferObj.buffer.getChannelData(c);
-                            for (var n=0; n<waveObj.num_samples; n++)
-                            {
+                            for (var n = 0; n < waveObj.num_samples; n++) {
                                 buffer_ptr[n] = waveObj.decoded_data[c][n];
                             }
                         }
 
                         delete waveObj;
                     }
-                    if (bufferObj.buffer != undefined)
-                    {
+                    if (bufferObj.buffer != undefined) {
                         bufferObj.status = 2;
-                        calculateLoudness(bufferObj,"I");
+                        calculateLoudness(bufferObj, "I");
                     }
                 });
-			};
-            
+            };
+
             // Create callback for any error in loading
-            this.xmlRequest.onerror = function() {
+            this.xmlRequest.onerror = function () {
                 this.parent.status = -1;
-                for (var i=0; i<this.parent.users.length; i++)
-                {
+                for (var i = 0; i < this.parent.users.length; i++) {
                     this.parent.users[i].state = -1;
-                    if (this.parent.users[i].interfaceDOM != null)
-                    {
+                    if (this.parent.users[i].interfaceDOM != null) {
                         this.parent.users[i].bufferLoaded(this);
                     }
                 }
-                interfaceContext.lightbox.post("Error","Could not load resource "+this.parent.url);
+                interfaceContext.lightbox.post("Error", "Could not load resource " + this.parent.url);
             }
-            
-			this.progress = 0;
-			this.progressCallback = function(event){
-				if (event.lengthComputable)
-				{
-					this.parent.progress = event.loaded / event.total;
-					for (var i=0; i<this.parent.users.length; i++)
-					{
-						if(this.parent.users[i].interfaceDOM != null)
-						{
-							if (typeof this.parent.users[i].interfaceDOM.updateLoading === "function")
-							{
-								this.parent.users[i].interfaceDOM.updateLoading(this.parent.progress*100);
-							}
-						}
-					}
-				}
-			};
-			this.xmlRequest.addEventListener("progress", this.progressCallback);
+
+            this.progress = 0;
+            this.progressCallback = function (event) {
+                if (event.lengthComputable) {
+                    this.parent.progress = event.loaded / event.total;
+                    for (var i = 0; i < this.parent.users.length; i++) {
+                        if (this.parent.users[i].interfaceDOM != null) {
+                            if (typeof this.parent.users[i].interfaceDOM.updateLoading === "function") {
+                                this.parent.users[i].interfaceDOM.updateLoading(this.parent.progress * 100);
+                            }
+                        }
+                    }
+                }
+            };
+            this.xmlRequest.addEventListener("progress", this.progressCallback);
             this.status = 1;
-			this.xmlRequest.send();
-		};
-        
-        this.registerAudioObject = function(audioObject)
-        {
+            this.xmlRequest.send();
+        };
+
+        this.registerAudioObject = function (audioObject) {
             // Called by an audioObject to register to the buffer for use
             // First check if already in the register pool
-            for (var objects of this.users)
-            {
-                if (audioObject.id == objects.id){return 0;}
+            for (var objects of this.users) {
+                if (audioObject.id == objects.id) {
+                    return 0;
+                }
             }
             this.users.push(audioObject);
-            if (this.status == 3 || this.status == -1)
-            {
+            if (this.status == 3 || this.status == -1) {
                 // The buffer is already ready, trigger bufferLoaded
                 audioObject.bufferLoaded(this);
             }
         };
-        
-        this.copyBuffer = function(preSilenceTime,postSilenceTime) {
+
+        this.copyBuffer = function (preSilenceTime, postSilenceTime) {
             // Copies the entire bufferObj.
-            if (preSilenceTime == undefined) {preSilenceTime = 0;}
-            if (postSilenceTime == undefined) {postSilenceTime = 0;}
-            var preSilenceSamples = secondsToSamples(preSilenceTime,this.buffer.sampleRate);
-            var postSilenceSamples = secondsToSamples(postSilenceTime,this.buffer.sampleRate);
-            var newLength = this.buffer.length+preSilenceSamples+postSilenceSamples;
+            if (preSilenceTime == undefined) {
+                preSilenceTime = 0;
+            }
+            if (postSilenceTime == undefined) {
+                postSilenceTime = 0;
+            }
+            var preSilenceSamples = secondsToSamples(preSilenceTime, this.buffer.sampleRate);
+            var postSilenceSamples = secondsToSamples(postSilenceTime, this.buffer.sampleRate);
+            var newLength = this.buffer.length + preSilenceSamples + postSilenceSamples;
             var copybuffer = audioContext.createBuffer(this.buffer.numberOfChannels, newLength, this.buffer.sampleRate);
             // Now we can use some efficient background copy schemes if we are just padding the end
             if (preSilenceSamples == 0 && typeof copybuffer.copyToChannel == "function") {
-                for (var c=0; c<this.buffer.numberOfChannels; c++) {
-                    copybuffer.copyToChannel(this.buffer.getChannelData(c),c);
+                for (var c = 0; c < this.buffer.numberOfChannels; c++) {
+                    copybuffer.copyToChannel(this.buffer.getChannelData(c), c);
                 }
             } else {
-                for (var c=0; c<this.buffer.numberOfChannels; c++) {
+                for (var c = 0; c < this.buffer.numberOfChannels; c++) {
                     var src = this.buffer.getChannelData(c);
                     var dst = copybuffer.getChannelData(c);
-                    for (var n=0; n<src.length; n++)
-                        dst[n+preSilenceSamples] = src[n];
+                    for (var n = 0; n < src.length; n++)
+                        dst[n + preSilenceSamples] = src[n];
                 }
             }
             // Copy in the rest of the buffer information
@@ -1527,30 +1517,30 @@
             copybuffer.playbackGain = this.buffer.playbackGain;
             return copybuffer;
         }
-        
-        this.cropBuffer = function(startTime, stopTime) {
+
+        this.cropBuffer = function (startTime, stopTime) {
             // Copy and return the cropped buffer
-            var start_sample = Math.floor(startTime*this.buffer.sampleRate);
-            var stop_sample = Math.floor(stopTime*this.buffer.sampleRate);
+            var start_sample = Math.floor(startTime * this.buffer.sampleRate);
+            var stop_sample = Math.floor(stopTime * this.buffer.sampleRate);
             var newLength = stop_sample - start_sample;
             var copybuffer = audioContext.createBuffer(this.buffer.numberOfChannels, newLength, this.buffer.sampleRate);
             // Now we can use some efficient background copy schemes if we are just padding the end
-            for (var c=0; c<this.buffer.numberOfChannels; c++) {
+            for (var c = 0; c < this.buffer.numberOfChannels; c++) {
                 var buffer = this.buffer.getChannelData(c);
-                var sub_frame = buffer.subarray(start_sample,stop_sample);
+                var sub_frame = buffer.subarray(start_sample, stop_sample);
                 if (typeof copybuffer.copyToChannel == "function") {
-                    copybuffer.copyToChannel(sub_frame,c);
+                    copybuffer.copyToChannel(sub_frame, c);
                 } else {
                     var dst = copybuffer.getChannelData(c);
-                    for (var n=0; n<newLength; n++)
-                        dst[n] = src[n+start_sample];
+                    for (var n = 0; n < newLength; n++)
+                        dst[n] = src[n + start_sample];
                 }
             }
             return copybuffer;
         }
-	};
-    
-    this.loadPageData = function(page) {
+    };
+
+    this.loadPageData = function (page) {
         // Load the URL from pages
         for (var element of page.audioElements) {
             var URL = page.hostURL + element.url;
@@ -1568,217 +1558,207 @@
             }
         }
     };
-	
-	this.play = function(id) {
-		// Start the timer and set the audioEngine state to playing (1)
-		if (this.status == 0) {
-			// Check if all audioObjects are ready
-			this.bufferReady(id);
-		}
-		else
-		{
-			this.status = 1;
-		}
-		if (this.status== 1) {
-			this.timer.startTest();
-			if (id == undefined) {
-				id = -1;
-				console.error('FATAL - Passed id was undefined - AudioEngineContext.play(id)');
-				return;
-			} else {
-				interfaceContext.playhead.setTimePerPixel(this.audioObjects[id]);
-			}
-			if (this.synchPlayback && this.loopPlayback) {
+
+    this.play = function (id) {
+        // Start the timer and set the audioEngine state to playing (1)
+        if (this.status == 0) {
+            // Check if all audioObjects are ready
+            this.bufferReady(id);
+        } else {
+            this.status = 1;
+        }
+        if (this.status == 1) {
+            this.timer.startTest();
+            if (id == undefined) {
+                id = -1;
+                console.error('FATAL - Passed id was undefined - AudioEngineContext.play(id)');
+                return;
+            } else {
+                interfaceContext.playhead.setTimePerPixel(this.audioObjects[id]);
+            }
+            if (this.synchPlayback && this.loopPlayback) {
                 // Traditional looped playback
-                var setTime = audioContext.currentTime+specification.crossFade;
-				for (var i=0; i<this.audioObjects.length; i++)
-				{
-					this.audioObjects[i].play(audioContext.currentTime);
-					if (id == i) {
-						this.audioObjects[i].loopStart(setTime);
-					} else {
-						this.audioObjects[i].loopStop(setTime);
-					}
-				}
+                var setTime = audioContext.currentTime + specification.crossFade;
+                for (var i = 0; i < this.audioObjects.length; i++) {
+                    this.audioObjects[i].play(audioContext.currentTime);
+                    if (id == i) {
+                        this.audioObjects[i].loopStart(setTime);
+                    } else {
+                        this.audioObjects[i].loopStop(setTime);
+                    }
+                }
             } else {
-                var setTime = audioContext.currentTime+specification.crossFade;
-				for (var i=0; i<this.audioObjects.length; i++)
-				{
-					if (i != id) {
-						this.audioObjects[i].stop(setTime);
-					} else if (i == id) {
-						this.audioObjects[id].play(setTime);
-					}
-				}
-			}
-			interfaceContext.playhead.start();
-		}
-	};
-	
-	this.stop = function() {
-		// Send stop and reset command to all playback buffers
-		if (this.status == 1) {
-            var setTime = audioContext.currentTime+0.1;
-			for (var i=0; i<this.audioObjects.length; i++)
-			{
-				this.audioObjects[i].stop(setTime);
-			}
-			interfaceContext.playhead.stop();
-		}
-	};
-	
-	this.newTrack = function(element) {
-		// Pull data from given URL into new audio buffer
-		// URLs must either be from the same source OR be setup to 'Access-Control-Allow-Origin'
-		
-		// Create the audioObject with ID of the new track length;
-		audioObjectId = this.audioObjects.length;
-		this.audioObjects[audioObjectId] = new audioObject(audioObjectId);
+                var setTime = audioContext.currentTime + specification.crossFade;
+                for (var i = 0; i < this.audioObjects.length; i++) {
+                    if (i != id) {
+                        this.audioObjects[i].stop(setTime);
+                    } else if (i == id) {
+                        this.audioObjects[id].play(setTime);
+                    }
+                }
+            }
+            interfaceContext.playhead.start();
+        }
+    };
 
-		// Check if audioObject buffer is currently stored by full URL
-		var URL = testState.currentStateMap.hostURL + element.url;
-		var buffer = null;
-		for (var i=0; i<this.buffers.length; i++)
-		{
-			if (URL == this.buffers[i].url)
-			{
-				buffer = this.buffers[i];
-				break;
-			}
-		}
-		if (buffer == null)
-		{
-			console.log("[WARN]: Buffer was not loaded in pre-test! "+URL);
-			buffer = new this.bufferObj();
+    this.stop = function () {
+        // Send stop and reset command to all playback buffers
+        if (this.status == 1) {
+            var setTime = audioContext.currentTime + 0.1;
+            for (var i = 0; i < this.audioObjects.length; i++) {
+                this.audioObjects[i].stop(setTime);
+            }
+            interfaceContext.playhead.stop();
+        }
+    };
+
+    this.newTrack = function (element) {
+        // Pull data from given URL into new audio buffer
+        // URLs must either be from the same source OR be setup to 'Access-Control-Allow-Origin'
+
+        // Create the audioObject with ID of the new track length;
+        audioObjectId = this.audioObjects.length;
+        this.audioObjects[audioObjectId] = new audioObject(audioObjectId);
+
+        // Check if audioObject buffer is currently stored by full URL
+        var URL = testState.currentStateMap.hostURL + element.url;
+        var buffer = null;
+        for (var i = 0; i < this.buffers.length; i++) {
+            if (URL == this.buffers[i].url) {
+                buffer = this.buffers[i];
+                break;
+            }
+        }
+        if (buffer == null) {
+            console.log("[WARN]: Buffer was not loaded in pre-test! " + URL);
+            buffer = new this.bufferObj();
             this.buffers.push(buffer);
-			buffer.getMedia(URL);
-		}
-		this.audioObjects[audioObjectId].specification = element;
-		this.audioObjects[audioObjectId].url = URL;
-		// Obtain store node
-		var aeNodes = this.pageStore.XMLDOM.getElementsByTagName('audioelement');
-		for (var i=0; i<aeNodes.length; i++)
-		{
-			if(aeNodes[i].getAttribute("ref") == element.id)
-			{
-				this.audioObjects[audioObjectId].storeDOM = aeNodes[i];
-				break;
-			}
-		}
+            buffer.getMedia(URL);
+        }
+        this.audioObjects[audioObjectId].specification = element;
+        this.audioObjects[audioObjectId].url = URL;
+        // Obtain store node
+        var aeNodes = this.pageStore.XMLDOM.getElementsByTagName('audioelement');
+        for (var i = 0; i < aeNodes.length; i++) {
+            if (aeNodes[i].getAttribute("ref") == element.id) {
+                this.audioObjects[audioObjectId].storeDOM = aeNodes[i];
+                break;
+            }
+        }
         buffer.registerAudioObject(this.audioObjects[audioObjectId]);
-		return this.audioObjects[audioObjectId];
-	};
-	
-	this.newTestPage = function(audioHolderObject,store) {
-		this.pageStore = store;
+        return this.audioObjects[audioObjectId];
+    };
+
+    this.newTestPage = function (audioHolderObject, store) {
+        this.pageStore = store;
         this.pageSpecification = audioHolderObject;
-		this.status = 0;
-		this.audioObjectsReady = false;
-		this.metric.reset();
-		for (var i=0; i < this.buffers.length; i++)
-		{
-			this.buffers[i].users = [];
-		}
-		this.audioObjects = [];
+        this.status = 0;
+        this.audioObjectsReady = false;
+        this.metric.reset();
+        for (var i = 0; i < this.buffers.length; i++) {
+            this.buffers[i].users = [];
+        }
+        this.audioObjects = [];
         this.timer = new timer();
         this.loopPlayback = audioHolderObject.loop;
         this.synchPlayback = audioHolderObject.synchronous;
-	};
-	
-	this.checkAllPlayed = function() {
-		arr = [];
-		for (var id=0; id<this.audioObjects.length; id++) {
-			if (this.audioObjects[id].metric.wasListenedTo == false) {
-				arr.push(this.audioObjects[id].id);
-			}
-		}
-		return arr;
-	};
-	
-	this.checkAllReady = function() {
-		var ready = true;
-		for (var i=0; i<this.audioObjects.length; i++) {
-			if (this.audioObjects[i].state == 0) {
-				// Track not ready
-				console.log('WAIT -- audioObject '+i+' not ready yet!');
-				ready = false;
-			};
-		}
-		return ready;
-	};
-	
-	this.setSynchronousLoop = function() {
-		// Pads the signals so they are all exactly the same length
+    };
+
+    this.checkAllPlayed = function () {
+        arr = [];
+        for (var id = 0; id < this.audioObjects.length; id++) {
+            if (this.audioObjects[id].metric.wasListenedTo == false) {
+                arr.push(this.audioObjects[id].id);
+            }
+        }
+        return arr;
+    };
+
+    this.checkAllReady = function () {
+        var ready = true;
+        for (var i = 0; i < this.audioObjects.length; i++) {
+            if (this.audioObjects[i].state == 0) {
+                // Track not ready
+                console.log('WAIT -- audioObject ' + i + ' not ready yet!');
+                ready = false;
+            };
+        }
+        return ready;
+    };
+
+    this.setSynchronousLoop = function () {
+        // Pads the signals so they are all exactly the same length
         // Get the length of the longest signal.
-		var length = 0;
-		var maxId;
-		for (var i=0; i<this.audioObjects.length; i++)
-		{
-			if (length < this.audioObjects[i].buffer.buffer.length)
-			{
-				length = this.audioObjects[i].buffer.buffer.length;
-				maxId = i;
-			}
-		}
-		// Extract the audio and zero-pad
-		for (var ao of this.audioObjects)
-		{
+        var length = 0;
+        var maxId;
+        for (var i = 0; i < this.audioObjects.length; i++) {
+            if (length < this.audioObjects[i].buffer.buffer.length) {
+                length = this.audioObjects[i].buffer.buffer.length;
+                maxId = i;
+            }
+        }
+        // Extract the audio and zero-pad
+        for (var ao of this.audioObjects) {
             var lengthDiff = length - ao.buffer.buffer.length;
-			ao.buffer = ao.buffer.copyBuffer(0,samplesToSeconds(lengthDiff,ao.buffer.buffer.sampleRate));
-		}
-	};
-    
-    this.bufferReady = function(id) {
-        if(this.checkAllReady()) {
-            if (this.synchPlayback){this.setSynchronousLoop();}
+            if (lengthDiff > 0) {
+                ao.buffer.buffer = ao.buffer.copyBuffer(0, samplesToSeconds(lengthDiff, ao.buffer.buffer.sampleRate));
+            }
+        }
+    };
+
+    this.bufferReady = function (id) {
+        if (this.checkAllReady()) {
+            if (this.synchPlayback) {
+                this.setSynchronousLoop();
+            }
             this.status = 1;
             return true;
         }
         return false;
     }
-    
-    this.exportXML = function()
-    {
-        
+
+    this.exportXML = function () {
+
     };
-	
+
 }
 
 function audioObject(id) {
-	// The main buffer object with common control nodes to the AudioEngine
-	
-	this.specification;
-	this.id = id;
-	this.state = 0; // 0 - no data, 1 - ready
-	this.url = null; // Hold the URL given for the output back to the results.
-	this.metric = new metricTracker(this);
-	this.storeDOM = null;
-	
-	// Bindings for GUI
-	this.interfaceDOM = null;
-	this.commentDOM = null;
-	
-	// Create a buffer and external gain control to allow internal patching of effects and volume leveling.
-	this.bufferNode = undefined;
-	this.outputGain = audioContext.createGain();
-	
-	this.onplayGain = 1.0;
-	
-	// Connect buffer to the audio graph
-	this.outputGain.connect(audioEngineContext.outputGain);
-	
-	// the audiobuffer is not designed for multi-start playback
-	// When stopeed, the buffer node is deleted and recreated with the stored buffer.
-	this.buffer;
-	
-	this.bufferLoaded = function(callee)
-	{
-		// Called by the associated buffer when it has finished loading, will then 'bind' the buffer to the
-		// audioObject and trigger the interfaceDOM.enable() function for user feedback
+    // The main buffer object with common control nodes to the AudioEngine
+
+    this.specification;
+    this.id = id;
+    this.state = 0; // 0 - no data, 1 - ready
+    this.url = null; // Hold the URL given for the output back to the results.
+    this.metric = new metricTracker(this);
+    this.storeDOM = null;
+
+    // Bindings for GUI
+    this.interfaceDOM = null;
+    this.commentDOM = null;
+
+    // Create a buffer and external gain control to allow internal patching of effects and volume leveling.
+    this.bufferNode = undefined;
+    this.outputGain = audioContext.createGain();
+
+    this.onplayGain = 1.0;
+
+    // Connect buffer to the audio graph
+    this.outputGain.connect(audioEngineContext.outputGain);
+
+    // the audiobuffer is not designed for multi-start playback
+    // When stopeed, the buffer node is deleted and recreated with the stored buffer.
+    this.buffer;
+
+    this.bufferLoaded = function (callee) {
+        // Called by the associated buffer when it has finished loading, will then 'bind' the buffer to the
+        // audioObject and trigger the interfaceDOM.enable() function for user feedback
         if (callee.status == -1) {
             // ERROR
             this.state = -1;
-            if (this.interfaceDOM != null) {this.interfaceDOM.error();}
+            if (this.interfaceDOM != null) {
+                this.interfaceDOM.error();
+            }
             this.buffer = callee;
             return;
         }
@@ -1788,436 +1768,414 @@
         var startTime = this.specification.startTime;
         var stopTime = this.specification.stopTime;
         var copybuffer = new callee.constructor();
-        if (isFinite(startTime) || isFinite(stopTime)) {
-            copybuffer.buffer = callee.cropBuffer(startTime,stopTime);
+
+        copybuffer.buffer = callee.cropBuffer(startTime || 0, stopTime || callee.buffer.duration);
+        if (preSilenceTime != 0 || postSilenceTime != 0) {
+            copybuffer.buffer = copybuffer.copyBuffer(preSilenceTime, postSilenceTime);
         }
-        if (preSilenceTime != 0 || postSilenceTime != 0) {
-            if (copybuffer.buffer == undefined) {
-                copybuffer.buffer = callee.copyBuffer(preSilenceTime,postSilenceTime);
-            } else {
-                copybuffer.buffer = copybuffer.copyBuffer(preSilenceTime,postSilenceTime);
-            }
+
+        copybuffer.lufs = callee.buffer.lufs;
+        this.buffer = copybuffer;
+
+        var targetLUFS = this.specification.parent.loudness || specification.loudness;
+        if (typeof targetLUFS === "number" && isFinite(targetLUFS)) {
+            this.buffer.buffer.playbackGain = decibelToLinear(targetLUFS - this.buffer.buffer.lufs);
+        } else {
+            this.buffer.buffer.playbackGain = 1.0;
         }
-        
-		var targetLUFS = this.specification.parent.loudness || specification.loudness;
-		if (typeof targetLUFS === "number" && isFinite(targetLUFS))
-		{
-			this.buffer.buffer.playbackGain = decibelToLinear(targetLUFS - this.buffer.buffer.lufs);
-		} else {
-			this.buffer.buffer.playbackGain = 1.0;
-		}
-		if (this.interfaceDOM != null) {
-			this.interfaceDOM.enable();
-		}
-		this.onplayGain = decibelToLinear(this.specification.gain)*(this.buffer.buffer.playbackGain||1.0);
-		this.storeDOM.setAttribute('playGain',linearToDecibel(this.onplayGain));
+        if (this.interfaceDOM != null) {
+            this.interfaceDOM.enable();
+        }
+        this.onplayGain = decibelToLinear(this.specification.gain) * (this.buffer.buffer.playbackGain || 1.0);
+        this.storeDOM.setAttribute('playGain', linearToDecibel(this.onplayGain));
         this.state = 1;
         audioEngineContext.bufferReady(id);
-	};
-	
-	this.bindInterface = function(interfaceObject)
-	{
-		this.interfaceDOM = interfaceObject;
-		this.metric.initialise(interfaceObject.getValue());
-		if (this.state == 1)
-		{
-			this.interfaceDOM.enable();
-		} else if (this.state == -1) {
+    };
+
+    this.bindInterface = function (interfaceObject) {
+        this.interfaceDOM = interfaceObject;
+        this.metric.initialise(interfaceObject.getValue());
+        if (this.state == 1) {
+            this.interfaceDOM.enable();
+        } else if (this.state == -1) {
             // ERROR
             this.interfaceDOM.error();
             return;
         }
-		this.storeDOM.setAttribute('presentedId',interfaceObject.getPresentedId());
-	};
-    
-	this.loopStart = function(setTime) {
-		this.outputGain.gain.linearRampToValueAtTime(this.onplayGain,setTime);
-		this.metric.startListening(audioEngineContext.timer.getTestTime());
+        this.storeDOM.setAttribute('presentedId', interfaceObject.getPresentedId());
+    };
+
+    this.loopStart = function (setTime) {
+        this.outputGain.gain.linearRampToValueAtTime(this.onplayGain, setTime);
+        this.metric.startListening(audioEngineContext.timer.getTestTime());
         this.interfaceDOM.startPlayback();
-	};
-	
-	this.loopStop = function(setTime) {
-		if (this.outputGain.gain.value != 0.0) {
-			this.outputGain.gain.linearRampToValueAtTime(0.0,setTime);
-			this.metric.stopListening(audioEngineContext.timer.getTestTime());
-		}
+    };
+
+    this.loopStop = function (setTime) {
+        if (this.outputGain.gain.value != 0.0) {
+            this.outputGain.gain.linearRampToValueAtTime(0.0, setTime);
+            this.metric.stopListening(audioEngineContext.timer.getTestTime());
+        }
         this.interfaceDOM.stopPlayback();
-	};
-	
-	this.play = function(startTime) {
-		if (this.bufferNode == undefined && this.buffer.buffer != undefined) {
-			this.bufferNode = audioContext.createBufferSource();
-			this.bufferNode.owner = this;
-			this.bufferNode.connect(this.outputGain);
-			this.bufferNode.buffer = this.buffer.buffer;
-			this.bufferNode.loop = audioEngineContext.loopPlayback;
-			this.bufferNode.onended = function(event) {
-				// Safari does not like using 'this' to reference the calling object!
-				//event.currentTarget.owner.metric.stopListening(audioEngineContext.timer.getTestTime(),event.currentTarget.owner.getCurrentPosition());
+    };
+
+    this.play = function (startTime) {
+        if (this.bufferNode == undefined && this.buffer.buffer != undefined) {
+            this.bufferNode = audioContext.createBufferSource();
+            this.bufferNode.owner = this;
+            this.bufferNode.connect(this.outputGain);
+            this.bufferNode.buffer = this.buffer.buffer;
+            this.bufferNode.loop = audioEngineContext.loopPlayback;
+            this.bufferNode.onended = function (event) {
+                // Safari does not like using 'this' to reference the calling object!
+                //event.currentTarget.owner.metric.stopListening(audioEngineContext.timer.getTestTime(),event.currentTarget.owner.getCurrentPosition());
                 if (event.currentTarget != null) {
-				    event.currentTarget.owner.stop(audioContext.currentTime+1);
+                    event.currentTarget.owner.stop(audioContext.currentTime + 1);
                 }
-			};
-			if (!audioEngineContext.loopPlayback || !audioEngineContext.synchPlayback) {
-				this.metric.startListening(audioEngineContext.timer.getTestTime());
-                this.outputGain.gain.setValueAtTime(this.onplayGain,0.0);
+            };
+            if (!audioEngineContext.loopPlayback || !audioEngineContext.synchPlayback) {
+                this.metric.startListening(audioEngineContext.timer.getTestTime());
+                this.outputGain.gain.setValueAtTime(this.onplayGain, 0.0);
                 this.interfaceDOM.startPlayback();
-			} else {
-                 this.outputGain.gain.setValueAtTime(0.0,startTime);
+            } else {
+                this.outputGain.gain.setValueAtTime(0.0, startTime);
             }
-			this.bufferNode.start(startTime,this.specification.startTime || 0, this.specification.stopTime-this.specification.startTime || this.buffer.buffer.duration);
+            if (audioEngineContext.loopPlayback) {
+                this.bufferNode.loopStart = this.specification.startTime || 0;
+                this.bufferNode.loopEnd = this.specification.stopTime - this.specification.startTime || this.buffer.buffer.duration;
+                this.bufferNode.start(startTime);
+            } else {
+                this.bufferNode.start(startTime, this.specification.startTime || 0, this.specification.stopTime - this.specification.startTime || this.buffer.buffer.duration);
+            }
             this.bufferNode.playbackStartTime = audioEngineContext.timer.getTestTime();
-		}
-	};
-	
-	this.stop = function(stopTime) {
+        }
+    };
+
+    this.stop = function (stopTime) {
         this.outputGain.gain.cancelScheduledValues(audioContext.currentTime);
-		if (this.bufferNode != undefined)
-		{
-			this.metric.stopListening(audioEngineContext.timer.getTestTime(),this.getCurrentPosition());
-			this.bufferNode.stop(stopTime);
-			this.bufferNode = undefined;
-		}
+        if (this.bufferNode != undefined) {
+            this.metric.stopListening(audioEngineContext.timer.getTestTime(), this.getCurrentPosition());
+            this.bufferNode.stop(stopTime);
+            this.bufferNode = undefined;
+        }
         this.outputGain.gain.value = 0.0;
         this.interfaceDOM.stopPlayback();
-	};
-	
-	this.getCurrentPosition = function() {
-		var time = audioEngineContext.timer.getTestTime();
-		if (this.bufferNode != undefined) {
-            var position = (time - this.bufferNode.playbackStartTime)%this.buffer.buffer.duration;
-            if (isNaN(position)){return 0;}
+    };
+
+    this.getCurrentPosition = function () {
+        var time = audioEngineContext.timer.getTestTime();
+        if (this.bufferNode != undefined) {
+            var position = (time - this.bufferNode.playbackStartTime) % this.buffer.buffer.duration;
+            if (isNaN(position)) {
+                return 0;
+            }
             return position;
-		} else {
-			return 0;
-		}
-	};
-	
-	this.exportXMLDOM = function() {
-		var file = storage.document.createElement('file');
-		file.setAttribute('sampleRate',this.buffer.buffer.sampleRate);
-		file.setAttribute('channels',this.buffer.buffer.numberOfChannels);
-		file.setAttribute('sampleCount',this.buffer.buffer.length);
-		file.setAttribute('duration',this.buffer.buffer.duration);
-		this.storeDOM.appendChild(file);
-		if (this.specification.type != 'outside-reference') {
-			var interfaceXML = this.interfaceDOM.exportXMLDOM(this);
-			if (interfaceXML != null)
-			{
-				if (interfaceXML.length == undefined) {
-					this.storeDOM.appendChild(interfaceXML);
-				} else {
-					for (var i=0; i<interfaceXML.length; i++)
-					{
-						this.storeDOM.appendChild(interfaceXML[i]);
-					}
-				}
-			}
-			if (this.commentDOM != null) {
-				this.storeDOM.appendChild(this.commentDOM.exportXMLDOM(this));
-			}
-		}
-		var nodes = this.metric.exportXMLDOM();
-		var mroot = this.storeDOM.getElementsByTagName('metric')[0];
-		for (var i=0; i<nodes.length; i++)
-		{
-			mroot.appendChild(nodes[i]);
-		}
-	};
+        } else {
+            return 0;
+        }
+    };
+
+    this.exportXMLDOM = function () {
+        var file = storage.document.createElement('file');
+        file.setAttribute('sampleRate', this.buffer.buffer.sampleRate);
+        file.setAttribute('channels', this.buffer.buffer.numberOfChannels);
+        file.setAttribute('sampleCount', this.buffer.buffer.length);
+        file.setAttribute('duration', this.buffer.buffer.duration);
+        this.storeDOM.appendChild(file);
+        if (this.specification.type != 'outside-reference') {
+            var interfaceXML = this.interfaceDOM.exportXMLDOM(this);
+            if (interfaceXML != null) {
+                if (interfaceXML.length == undefined) {
+                    this.storeDOM.appendChild(interfaceXML);
+                } else {
+                    for (var i = 0; i < interfaceXML.length; i++) {
+                        this.storeDOM.appendChild(interfaceXML[i]);
+                    }
+                }
+            }
+            if (this.commentDOM != null) {
+                this.storeDOM.appendChild(this.commentDOM.exportXMLDOM(this));
+            }
+        }
+        var nodes = this.metric.exportXMLDOM();
+        var mroot = this.storeDOM.getElementsByTagName('metric')[0];
+        for (var i = 0; i < nodes.length; i++) {
+            mroot.appendChild(nodes[i]);
+        }
+    };
 }
 
-function timer()
-{
-	/* Timer object used in audioEngine to keep track of session timings
-	 * Uses the timer of the web audio API, so sample resolution
-	 */
-	this.testStarted = false;
-	this.testStartTime = 0;
-	this.testDuration = 0;
-	this.minimumTestTime = 0; // No minimum test time
-	this.startTest = function()
-	{
-		if (this.testStarted == false)
-		{
-			this.testStartTime = audioContext.currentTime;
-			this.testStarted = true;
-			this.updateTestTime();
-			audioEngineContext.metric.initialiseTest();
-		}
-	};
-	this.stopTest = function()
-	{
-		if (this.testStarted)
-		{
-			this.testDuration = this.getTestTime();
-			this.testStarted = false;
-		} else {
-			console.log('ERR: Test tried to end before beginning');
-		}
-	};
-	this.updateTestTime = function()
-	{
-		if (this.testStarted)
-		{
-			this.testDuration = audioContext.currentTime - this.testStartTime;
-		}
-	};
-	this.getTestTime = function()
-	{
-		this.updateTestTime();
-		return this.testDuration;
-	};
+function timer() {
+    /* Timer object used in audioEngine to keep track of session timings
+     * Uses the timer of the web audio API, so sample resolution
+     */
+    this.testStarted = false;
+    this.testStartTime = 0;
+    this.testDuration = 0;
+    this.minimumTestTime = 0; // No minimum test time
+    this.startTest = function () {
+        if (this.testStarted == false) {
+            this.testStartTime = audioContext.currentTime;
+            this.testStarted = true;
+            this.updateTestTime();
+            audioEngineContext.metric.initialiseTest();
+        }
+    };
+    this.stopTest = function () {
+        if (this.testStarted) {
+            this.testDuration = this.getTestTime();
+            this.testStarted = false;
+        } else {
+            console.log('ERR: Test tried to end before beginning');
+        }
+    };
+    this.updateTestTime = function () {
+        if (this.testStarted) {
+            this.testDuration = audioContext.currentTime - this.testStartTime;
+        }
+    };
+    this.getTestTime = function () {
+        this.updateTestTime();
+        return this.testDuration;
+    };
 }
 
-function sessionMetrics(engine,specification)
-{
-	/* Used by audioEngine to link to audioObjects to minimise the timer call timers;
-	 */
-	this.engine = engine;
-	this.lastClicked = -1;
-	this.data = -1;
-	this.reset = function() {
-		this.lastClicked = -1;
-		this.data = -1;
-	};
-	
-	this.enableElementInitialPosition = false;
-	this.enableElementListenTracker = false;
-	this.enableElementTimer = false;
-	this.enableElementTracker = false;
-	this.enableFlagListenedTo = false;
-	this.enableFlagMoved = false;
-	this.enableTestTimer = false;
-	// Obtain the metrics enabled
-	for (var i=0; i<specification.metrics.enabled.length; i++)
-	{
-		var node = specification.metrics.enabled[i];
-		switch(node)
-		{
-		case 'testTimer':
-			this.enableTestTimer = true;
-			break;
-		case 'elementTimer':
-			this.enableElementTimer = true;
-			break;
-		case 'elementTracker':
-			this.enableElementTracker = true;
-			break;
-		case 'elementListenTracker':
-			this.enableElementListenTracker = true;
-			break;
-		case 'elementInitialPosition':
-			this.enableElementInitialPosition = true;
-			break;
-		case 'elementFlagListenedTo':
-			this.enableFlagListenedTo = true;
-			break;
-		case 'elementFlagMoved':
-			this.enableFlagMoved = true;
-			break;
-		case 'elementFlagComments':
-			this.enableFlagComments = true;
-			break;
-		}
-	}
-	this.initialiseTest = function(){};
+function sessionMetrics(engine, specification) {
+    /* Used by audioEngine to link to audioObjects to minimise the timer call timers;
+     */
+    this.engine = engine;
+    this.lastClicked = -1;
+    this.data = -1;
+    this.reset = function () {
+        this.lastClicked = -1;
+        this.data = -1;
+    };
+
+    this.enableElementInitialPosition = false;
+    this.enableElementListenTracker = false;
+    this.enableElementTimer = false;
+    this.enableElementTracker = false;
+    this.enableFlagListenedTo = false;
+    this.enableFlagMoved = false;
+    this.enableTestTimer = false;
+    // Obtain the metrics enabled
+    for (var i = 0; i < specification.metrics.enabled.length; i++) {
+        var node = specification.metrics.enabled[i];
+        switch (node) {
+            case 'testTimer':
+                this.enableTestTimer = true;
+                break;
+            case 'elementTimer':
+                this.enableElementTimer = true;
+                break;
+            case 'elementTracker':
+                this.enableElementTracker = true;
+                break;
+            case 'elementListenTracker':
+                this.enableElementListenTracker = true;
+                break;
+            case 'elementInitialPosition':
+                this.enableElementInitialPosition = true;
+                break;
+            case 'elementFlagListenedTo':
+                this.enableFlagListenedTo = true;
+                break;
+            case 'elementFlagMoved':
+                this.enableFlagMoved = true;
+                break;
+            case 'elementFlagComments':
+                this.enableFlagComments = true;
+                break;
+        }
+    }
+    this.initialiseTest = function () {};
 }
 
-function metricTracker(caller)
-{
-	/* Custom object to track and collect metric data
-	 * Used only inside the audioObjects object.
-	 */
-	
-	this.listenedTimer = 0;
-	this.listenStart = 0;
-	this.listenHold = false;
-	this.initialPosition = -1;
-	this.movementTracker = [];
-	this.listenTracker =[];
-	this.wasListenedTo = false;
-	this.wasMoved = false;
-	this.hasComments = false;
-	this.parent = caller;
-	
-	this.initialise = function(position)
-	{
-		if (this.initialPosition == -1) {
-			this.initialPosition = position;
-			this.moved(0,position);
-		}
-	};
-	
-	this.moved = function(time,position)
-	{
-		if (time > 0) {this.wasMoved = true;}
-		this.movementTracker[this.movementTracker.length] = [time, position];
-	};
-	
-	this.startListening = function(time)
-	{
-		if (this.listenHold == false)
-		{
-			this.wasListenedTo = true;
-			this.listenStart = time;
-			this.listenHold = true;
-			
-			var evnt = document.createElement('event');
-			var testTime = document.createElement('testTime');
-			testTime.setAttribute('start',time);
-			var bufferTime = document.createElement('bufferTime');
-			bufferTime.setAttribute('start',this.parent.getCurrentPosition());
-			evnt.appendChild(testTime);
-			evnt.appendChild(bufferTime);
-			this.listenTracker.push(evnt);
-			
-			console.log('slider ' + this.parent.id + ' played (' + time + ')'); // DEBUG/SAFETY: show played slider id
-		}
-	};
-	
-	this.stopListening = function(time,bufferStopTime)
-	{
-		if (this.listenHold == true)
-		{
-			var diff = time - this.listenStart;
-			this.listenedTimer += (diff);
-			this.listenStart = 0;
-			this.listenHold = false;
-			
-			var evnt = this.listenTracker[this.listenTracker.length-1];
-			var testTime = evnt.getElementsByTagName('testTime')[0];
-			var bufferTime = evnt.getElementsByTagName('bufferTime')[0];
-			testTime.setAttribute('stop',time);
-			if (bufferStopTime == undefined) {
-				bufferTime.setAttribute('stop',this.parent.getCurrentPosition());
-			} else {
-				bufferTime.setAttribute('stop',bufferStopTime);
-			}
-			console.log('slider ' + this.parent.id + ' played for (' + diff + ')'); // DEBUG/SAFETY: show played slider id
-		}
-	};
-	
-	this.exportXMLDOM = function() {
-		var storeDOM = [];
-		if (audioEngineContext.metric.enableElementTimer) {
-			var mElementTimer = storage.document.createElement('metricresult');
-			mElementTimer.setAttribute('name','enableElementTimer');
-			mElementTimer.textContent = this.listenedTimer;
-			storeDOM.push(mElementTimer);
-		}
-		if (audioEngineContext.metric.enableElementTracker) {
-			var elementTrackerFull = storage.document.createElement('metricresult');
-			elementTrackerFull.setAttribute('name','elementTrackerFull');
-			for (var k=0; k<this.movementTracker.length; k++)
-			{
-				var timePos = storage.document.createElement('movement');
-                timePos.setAttribute("time",this.movementTracker[k][0]);
-                timePos.setAttribute("value",this.movementTracker[k][1]);
-				elementTrackerFull.appendChild(timePos);
-			}
-			storeDOM.push(elementTrackerFull);
-		}
-		if (audioEngineContext.metric.enableElementListenTracker) {
-			var elementListenTracker = storage.document.createElement('metricresult');
-			elementListenTracker.setAttribute('name','elementListenTracker');
-			for (var k=0; k<this.listenTracker.length; k++) {
-				elementListenTracker.appendChild(this.listenTracker[k]);
-			}
-			storeDOM.push(elementListenTracker);
-		}
-		if (audioEngineContext.metric.enableElementInitialPosition) {
-			var elementInitial = storage.document.createElement('metricresult');
-			elementInitial.setAttribute('name','elementInitialPosition');
-			elementInitial.textContent = this.initialPosition;
-			storeDOM.push(elementInitial);
-		}
-		if (audioEngineContext.metric.enableFlagListenedTo) {
-			var flagListenedTo = storage.document.createElement('metricresult');
-			flagListenedTo.setAttribute('name','elementFlagListenedTo');
-			flagListenedTo.textContent = this.wasListenedTo;
-			storeDOM.push(flagListenedTo);
-		}
-		if (audioEngineContext.metric.enableFlagMoved) {
-			var flagMoved = storage.document.createElement('metricresult');
-			flagMoved.setAttribute('name','elementFlagMoved');
-			flagMoved.textContent = this.wasMoved;
-			storeDOM.push(flagMoved);
-		}
-		if (audioEngineContext.metric.enableFlagComments) {
-			var flagComments = storage.document.createElement('metricresult');
-			flagComments.setAttribute('name','elementFlagComments');
-			if (this.parent.commentDOM == null)
-				{flag.textContent = 'false';}
-			else if (this.parent.commentDOM.textContent.length == 0) 
-				{flag.textContent = 'false';}
-			else 
-				{flag.textContet = 'true';}
-			storeDOM.push(flagComments);
-		}
-		return storeDOM;
-	};
+function metricTracker(caller) {
+    /* Custom object to track and collect metric data
+     * Used only inside the audioObjects object.
+     */
+
+    this.listenedTimer = 0;
+    this.listenStart = 0;
+    this.listenHold = false;
+    this.initialPosition = -1;
+    this.movementTracker = [];
+    this.listenTracker = [];
+    this.wasListenedTo = false;
+    this.wasMoved = false;
+    this.hasComments = false;
+    this.parent = caller;
+
+    this.initialise = function (position) {
+        if (this.initialPosition == -1) {
+            this.initialPosition = position;
+            this.moved(0, position);
+        }
+    };
+
+    this.moved = function (time, position) {
+        if (time > 0) {
+            this.wasMoved = true;
+        }
+        this.movementTracker[this.movementTracker.length] = [time, position];
+    };
+
+    this.startListening = function (time) {
+        if (this.listenHold == false) {
+            this.wasListenedTo = true;
+            this.listenStart = time;
+            this.listenHold = true;
+
+            var evnt = document.createElement('event');
+            var testTime = document.createElement('testTime');
+            testTime.setAttribute('start', time);
+            var bufferTime = document.createElement('bufferTime');
+            bufferTime.setAttribute('start', this.parent.getCurrentPosition());
+            evnt.appendChild(testTime);
+            evnt.appendChild(bufferTime);
+            this.listenTracker.push(evnt);
+
+            console.log('slider ' + this.parent.id + ' played (' + time + ')'); // DEBUG/SAFETY: show played slider id
+        }
+    };
+
+    this.stopListening = function (time, bufferStopTime) {
+        if (this.listenHold == true) {
+            var diff = time - this.listenStart;
+            this.listenedTimer += (diff);
+            this.listenStart = 0;
+            this.listenHold = false;
+
+            var evnt = this.listenTracker[this.listenTracker.length - 1];
+            var testTime = evnt.getElementsByTagName('testTime')[0];
+            var bufferTime = evnt.getElementsByTagName('bufferTime')[0];
+            testTime.setAttribute('stop', time);
+            if (bufferStopTime == undefined) {
+                bufferTime.setAttribute('stop', this.parent.getCurrentPosition());
+            } else {
+                bufferTime.setAttribute('stop', bufferStopTime);
+            }
+            console.log('slider ' + this.parent.id + ' played for (' + diff + ')'); // DEBUG/SAFETY: show played slider id
+        }
+    };
+
+    this.exportXMLDOM = function () {
+        var storeDOM = [];
+        if (audioEngineContext.metric.enableElementTimer) {
+            var mElementTimer = storage.document.createElement('metricresult');
+            mElementTimer.setAttribute('name', 'enableElementTimer');
+            mElementTimer.textContent = this.listenedTimer;
+            storeDOM.push(mElementTimer);
+        }
+        if (audioEngineContext.metric.enableElementTracker) {
+            var elementTrackerFull = storage.document.createElement('metricresult');
+            elementTrackerFull.setAttribute('name', 'elementTrackerFull');
+            for (var k = 0; k < this.movementTracker.length; k++) {
+                var timePos = storage.document.createElement('movement');
+                timePos.setAttribute("time", this.movementTracker[k][0]);
+                timePos.setAttribute("value", this.movementTracker[k][1]);
+                elementTrackerFull.appendChild(timePos);
+            }
+            storeDOM.push(elementTrackerFull);
+        }
+        if (audioEngineContext.metric.enableElementListenTracker) {
+            var elementListenTracker = storage.document.createElement('metricresult');
+            elementListenTracker.setAttribute('name', 'elementListenTracker');
+            for (var k = 0; k < this.listenTracker.length; k++) {
+                elementListenTracker.appendChild(this.listenTracker[k]);
+            }
+            storeDOM.push(elementListenTracker);
+        }
+        if (audioEngineContext.metric.enableElementInitialPosition) {
+            var elementInitial = storage.document.createElement('metricresult');
+            elementInitial.setAttribute('name', 'elementInitialPosition');
+            elementInitial.textContent = this.initialPosition;
+            storeDOM.push(elementInitial);
+        }
+        if (audioEngineContext.metric.enableFlagListenedTo) {
+            var flagListenedTo = storage.document.createElement('metricresult');
+            flagListenedTo.setAttribute('name', 'elementFlagListenedTo');
+            flagListenedTo.textContent = this.wasListenedTo;
+            storeDOM.push(flagListenedTo);
+        }
+        if (audioEngineContext.metric.enableFlagMoved) {
+            var flagMoved = storage.document.createElement('metricresult');
+            flagMoved.setAttribute('name', 'elementFlagMoved');
+            flagMoved.textContent = this.wasMoved;
+            storeDOM.push(flagMoved);
+        }
+        if (audioEngineContext.metric.enableFlagComments) {
+            var flagComments = storage.document.createElement('metricresult');
+            flagComments.setAttribute('name', 'elementFlagComments');
+            if (this.parent.commentDOM == null) {
+                flag.textContent = 'false';
+            } else if (this.parent.commentDOM.textContent.length == 0) {
+                flag.textContent = 'false';
+            } else {
+                flag.textContet = 'true';
+            }
+            storeDOM.push(flagComments);
+        }
+        return storeDOM;
+    };
 }
-			
+
 function Interface(specificationObject) {
-	// This handles the bindings between the interface and the audioEngineContext;
-	this.specification = specificationObject;
-	this.insertPoint = document.getElementById("topLevelBody");
-	
-	this.newPage = function(audioHolderObject,store)
-	{
-		audioEngineContext.newTestPage(audioHolderObject,store);
-		interfaceContext.commentBoxes.deleteCommentBoxes();
-		interfaceContext.deleteCommentQuestions();
-		loadTest(audioHolderObject,store);
-	};
-	
-	// Bounded by interface!!
-	// Interface object MUST have an exportXMLDOM method which returns the various DOM levels
-	// For example, APE returns  the slider position normalised in a <value> tag.
-	this.interfaceObjects = [];
-	this.interfaceObject = function(){};
-	
-	this.resizeWindow = function(event)
-	{
-		popup.resize(event);
+    // This handles the bindings between the interface and the audioEngineContext;
+    this.specification = specificationObject;
+    this.insertPoint = document.getElementById("topLevelBody");
+
+    this.newPage = function (audioHolderObject, store) {
+        audioEngineContext.newTestPage(audioHolderObject, store);
+        interfaceContext.commentBoxes.deleteCommentBoxes();
+        interfaceContext.deleteCommentQuestions();
+        loadTest(audioHolderObject, store);
+    };
+
+    // Bounded by interface!!
+    // Interface object MUST have an exportXMLDOM method which returns the various DOM levels
+    // For example, APE returns  the slider position normalised in a <value> tag.
+    this.interfaceObjects = [];
+    this.interfaceObject = function () {};
+
+    this.resizeWindow = function (event) {
+        popup.resize(event);
         this.volume.resize();
         this.lightbox.resize();
-		for(var i=0; i<this.commentBoxes.length; i++)
-		{this.commentBoxes[i].resize();}
-		for(var i=0; i<this.commentQuestions.length; i++)
-		{this.commentQuestions[i].resize();}
-		try
-		{
-			resizeWindow(event);
-		}
-		catch(err)
-		{
-			console.log("Warning - Interface does not have Resize option");
-			console.log(err);
-		}
-	};
-	
-	this.returnNavigator = function()
-	{
-		var node = storage.document.createElement("navigator");
-		var platform = storage.document.createElement("platform");
-		platform.textContent = navigator.platform;
-		var vendor = storage.document.createElement("vendor");
-		vendor.textContent = navigator.vendor;
-		var userAgent = storage.document.createElement("uagent");
-		userAgent.textContent = navigator.userAgent;
+        for (var i = 0; i < this.commentBoxes.length; i++) {
+            this.commentBoxes[i].resize();
+        }
+        for (var i = 0; i < this.commentQuestions.length; i++) {
+            this.commentQuestions[i].resize();
+        }
+        try {
+            resizeWindow(event);
+        } catch (err) {
+            console.log("Warning - Interface does not have Resize option");
+            console.log(err);
+        }
+    };
+
+    this.returnNavigator = function () {
+        var node = storage.document.createElement("navigator");
+        var platform = storage.document.createElement("platform");
+        platform.textContent = navigator.platform;
+        var vendor = storage.document.createElement("vendor");
+        vendor.textContent = navigator.vendor;
+        var userAgent = storage.document.createElement("uagent");
+        userAgent.textContent = navigator.userAgent;
         var screen = storage.document.createElement("window");
-        screen.setAttribute('innerWidth',window.innerWidth);
-        screen.setAttribute('innerHeight',window.innerHeight);
-		node.appendChild(platform);
-		node.appendChild(vendor);
-		node.appendChild(userAgent);
+        screen.setAttribute('innerWidth', window.innerWidth);
+        screen.setAttribute('innerHeight', window.innerHeight);
+        node.appendChild(platform);
+        node.appendChild(vendor);
+        node.appendChild(userAgent);
         node.appendChild(screen);
-		return node;
-	};
-    
-    this.returnDateNode = function()
-    {
+        return node;
+    };
+
+    this.returnDateNode = function () {
         // Create an XML Node for the Date and Time a test was conducted
         // Structure is
         // <datetime> 
@@ -2228,27 +2186,27 @@
         var hold = storage.document.createElement("datetime");
         var date = storage.document.createElement("date");
         var time = storage.document.createElement("time");
-        date.setAttribute('year',dateTime.getFullYear());
-        date.setAttribute('month',dateTime.getMonth()+1);
-        date.setAttribute('day',dateTime.getDate());
-        time.setAttribute('hour',dateTime.getHours());
-        time.setAttribute('minute',dateTime.getMinutes());
-        time.setAttribute('secs',dateTime.getSeconds());
-        
+        date.setAttribute('year', dateTime.getFullYear());
+        date.setAttribute('month', dateTime.getMonth() + 1);
+        date.setAttribute('day', dateTime.getDate());
+        time.setAttribute('hour', dateTime.getHours());
+        time.setAttribute('minute', dateTime.getMinutes());
+        time.setAttribute('secs', dateTime.getSeconds());
+
         hold.appendChild(date);
         hold.appendChild(time);
         return hold;
 
     }
-    
+
     this.lightbox = {
         parent: this,
         root: document.createElement("div"),
         content: document.createElement("div"),
         accept: document.createElement("button"),
         blanker: document.createElement("div"),
-        post: function(type,message) {
-            switch(type) {
+        post: function (type, message) {
+            switch (type) {
                 case "Error":
                     this.content.className = "lightbox-error";
                     break;
@@ -2264,25 +2222,25 @@
             this.content.appendChild(msg);
             this.show();
         },
-        show: function() {
+        show: function () {
             this.root.style.visibility = "visible";
             this.blanker.style.visibility = "visible";
         },
-        clear: function() {
+        clear: function () {
             this.root.style.visibility = "";
             this.blanker.style.visibility = "";
             this.content.textContent = "";
         },
-        handleEvent: function(event) {
+        handleEvent: function (event) {
             if (event.currentTarget == this.accept) {
                 this.clear();
             }
         },
-        resize: function(event) {
-            this.root.style.left = (window.innerWidth/2)-250 + 'px';
+        resize: function (event) {
+            this.root.style.left = (window.innerWidth / 2) - 250 + 'px';
         }
     }
-    
+
     this.lightbox.root.appendChild(this.lightbox.content);
     this.lightbox.root.appendChild(this.lightbox.accept);
     this.lightbox.root.className = "popupHolder";
@@ -2291,16 +2249,16 @@
     this.lightbox.accept.style.bottom = "10px";
     this.lightbox.accept.textContent = "OK";
     this.lightbox.accept.style.left = "237.5px";
-    this.lightbox.accept.addEventListener("click",this.lightbox);
+    this.lightbox.accept.addEventListener("click", this.lightbox);
     this.lightbox.blanker.className = "testHalt";
     this.lightbox.blanker.id = "lightbox-blanker";
     document.getElementsByTagName("body")[0].appendChild(this.lightbox.root);
     document.getElementsByTagName("body")[0].appendChild(this.lightbox.blanker);
-	
-	this.commentBoxes = new function() {
+
+    this.commentBoxes = new function () {
         this.boxes = [];
         this.injectPoint = null;
-        this.elementCommentBox = function(audioObject) {
+        this.elementCommentBox = function (audioObject) {
             var element = audioObject.specification;
             this.audioObject = audioObject;
             this.id = audioObject.id;
@@ -2308,15 +2266,15 @@
             // Create document objects to hold the comment boxes
             this.trackComment = document.createElement('div');
             this.trackComment.className = 'comment-div';
-            this.trackComment.id = 'comment-div-'+audioObject.id;
+            this.trackComment.id = 'comment-div-' + audioObject.id;
             // Create a string next to each comment asking for a comment
             this.trackString = document.createElement('span');
-            this.trackString.innerHTML = audioHolderObject.commentBoxPrefix+' '+audioObject.interfaceDOM.getPresentedId();
+            this.trackString.innerHTML = audioHolderObject.commentBoxPrefix + ' ' + audioObject.interfaceDOM.getPresentedId();
             // Create the HTML5 comment box 'textarea'
             this.trackCommentBox = document.createElement('textarea');
             this.trackCommentBox.rows = '4';
             this.trackCommentBox.cols = '100';
-            this.trackCommentBox.name = 'trackComment'+audioObject.id;
+            this.trackCommentBox.name = 'trackComment' + audioObject.id;
             this.trackCommentBox.className = 'trackComment';
             var br = document.createElement('br');
             // Add to the holder.
@@ -2324,52 +2282,52 @@
             this.trackComment.appendChild(br);
             this.trackComment.appendChild(this.trackCommentBox);
 
-            this.exportXMLDOM = function() {
+            this.exportXMLDOM = function () {
                 var root = document.createElement('comment');
                 var question = document.createElement('question');
                 question.textContent = this.trackString.textContent;
                 var response = document.createElement('response');
                 response.textContent = this.trackCommentBox.value;
-                console.log("Comment frag-"+this.id+": "+response.textContent);
+                console.log("Comment frag-" + this.id + ": " + response.textContent);
                 root.appendChild(question);
                 root.appendChild(response);
                 return root;
             };
-            this.resize = function()
-            {
-                var boxwidth = (window.innerWidth-100)/2;
-                if (boxwidth >= 600)
-                {
+            this.resize = function () {
+                var boxwidth = (window.innerWidth - 100) / 2;
+                if (boxwidth >= 600) {
                     boxwidth = 600;
-                }
-                else if (boxwidth < 400)
-                {
+                } else if (boxwidth < 400) {
                     boxwidth = 400;
                 }
-                this.trackComment.style.width = boxwidth+"px";
-                this.trackCommentBox.style.width = boxwidth-6+"px";
+                this.trackComment.style.width = boxwidth + "px";
+                this.trackCommentBox.style.width = boxwidth - 6 + "px";
             };
             this.resize();
         };
-        this.createCommentBox = function(audioObject) {
+        this.createCommentBox = function (audioObject) {
             var node = new this.elementCommentBox(audioObject);
             this.boxes.push(node);
             audioObject.commentDOM = node;
             return node;
         };
-        this.sortCommentBoxes = function() {
-            this.boxes.sort(function(a,b){return a.id - b.id;});
+        this.sortCommentBoxes = function () {
+            this.boxes.sort(function (a, b) {
+                return a.id - b.id;
+            });
         };
 
-        this.showCommentBoxes = function(inject, sort) {
+        this.showCommentBoxes = function (inject, sort) {
             this.injectPoint = inject;
-            if (sort) {this.sortCommentBoxes();}
+            if (sort) {
+                this.sortCommentBoxes();
+            }
             for (var box of this.boxes) {
                 inject.appendChild(box.trackComment);
             }
         };
 
-        this.deleteCommentBoxes = function() {
+        this.deleteCommentBoxes = function () {
             if (this.injectPoint != null) {
                 for (var box of this.boxes) {
                     this.injectPoint.removeChild(box.trackComment);
@@ -2379,34 +2337,34 @@
             this.boxes = [];
         };
     }
-	
-	this.commentQuestions = [];
-	
-	this.commentBox = function(commentQuestion) {
-		this.specification = commentQuestion;
-		// Create document objects to hold the comment boxes
-		this.holder = document.createElement('div');
-		this.holder.className = 'comment-div';
-		// Create a string next to each comment asking for a comment
-		this.string = document.createElement('span');
-		this.string.innerHTML = commentQuestion.statement;
-		// Create the HTML5 comment box 'textarea'
-		this.textArea = document.createElement('textarea');
-		this.textArea.rows = '4';
-		this.textArea.cols = '100';
-		this.textArea.className = 'trackComment';
-		var br = document.createElement('br');
-		// Add to the holder.
-		this.holder.appendChild(this.string);
-		this.holder.appendChild(br);
-		this.holder.appendChild(this.textArea);
-		
-		this.exportXMLDOM = function(storePoint) {
-			var root = storePoint.parent.document.createElement('comment');
-			root.id = this.specification.id;
-			root.setAttribute('type',this.specification.type);
-			console.log("Question: "+this.string.textContent);
-			console.log("Response: "+root.textContent);
+
+    this.commentQuestions = [];
+
+    this.commentBox = function (commentQuestion) {
+        this.specification = commentQuestion;
+        // Create document objects to hold the comment boxes
+        this.holder = document.createElement('div');
+        this.holder.className = 'comment-div';
+        // Create a string next to each comment asking for a comment
+        this.string = document.createElement('span');
+        this.string.innerHTML = commentQuestion.statement;
+        // Create the HTML5 comment box 'textarea'
+        this.textArea = document.createElement('textarea');
+        this.textArea.rows = '4';
+        this.textArea.cols = '100';
+        this.textArea.className = 'trackComment';
+        var br = document.createElement('br');
+        // Add to the holder.
+        this.holder.appendChild(this.string);
+        this.holder.appendChild(br);
+        this.holder.appendChild(this.textArea);
+
+        this.exportXMLDOM = function (storePoint) {
+            var root = storePoint.parent.document.createElement('comment');
+            root.id = this.specification.id;
+            root.setAttribute('type', this.specification.type);
+            console.log("Question: " + this.string.textContent);
+            console.log("Response: " + root.textContent);
             var question = storePoint.parent.document.createElement('question');
             question.textContent = this.string.textContent;
             var response = storePoint.parent.document.createElement('response');
@@ -2414,421 +2372,394 @@
             root.appendChild(question);
             root.appendChild(response);
             storePoint.XMLDOM.appendChild(root);
-			return root;
-		};
-		this.resize = function()
-		{
-			var boxwidth = (window.innerWidth-100)/2;
-			if (boxwidth >= 600)
-			{
-				boxwidth = 600;
-			}
-			else if (boxwidth < 400)
-			{
-				boxwidth = 400;
-			}
-			this.holder.style.width = boxwidth+"px";
-			this.textArea.style.width = boxwidth-6+"px";
-		};
-		this.resize();
-	};
-	
-	this.radioBox = function(commentQuestion) {
-		this.specification = commentQuestion;
-		// Create document objects to hold the comment boxes
-		this.holder = document.createElement('div');
-		this.holder.className = 'comment-div';
-		// Create a string next to each comment asking for a comment
-		this.string = document.createElement('span');
-		this.string.innerHTML = commentQuestion.statement;
-		var br = document.createElement('br');
-		// Add to the holder.
-		this.holder.appendChild(this.string);
-		this.holder.appendChild(br);
-		this.options = [];
-		this.inputs = document.createElement('div');
-		this.span = document.createElement('div');
-		this.inputs.align = 'center';
-		this.inputs.style.marginLeft = '12px';
+            return root;
+        };
+        this.resize = function () {
+            var boxwidth = (window.innerWidth - 100) / 2;
+            if (boxwidth >= 600) {
+                boxwidth = 600;
+            } else if (boxwidth < 400) {
+                boxwidth = 400;
+            }
+            this.holder.style.width = boxwidth + "px";
+            this.textArea.style.width = boxwidth - 6 + "px";
+        };
+        this.resize();
+    };
+
+    this.radioBox = function (commentQuestion) {
+        this.specification = commentQuestion;
+        // Create document objects to hold the comment boxes
+        this.holder = document.createElement('div');
+        this.holder.className = 'comment-div';
+        // Create a string next to each comment asking for a comment
+        this.string = document.createElement('span');
+        this.string.innerHTML = commentQuestion.statement;
+        var br = document.createElement('br');
+        // Add to the holder.
+        this.holder.appendChild(this.string);
+        this.holder.appendChild(br);
+        this.options = [];
+        this.inputs = document.createElement('div');
+        this.span = document.createElement('div');
+        this.inputs.align = 'center';
+        this.inputs.style.marginLeft = '12px';
         this.inputs.className = "comment-radio-inputs-holder";
-		this.span.style.marginLeft = '12px';
-		this.span.align = 'center';
-		this.span.style.marginTop = '15px';
+        this.span.style.marginLeft = '12px';
+        this.span.align = 'center';
+        this.span.style.marginTop = '15px';
         this.span.className = "comment-radio-span-holder";
-		
-		var optCount = commentQuestion.options.length;
-		for (var optNode of commentQuestion.options)
-		{
-			var div = document.createElement('div');
-			div.style.width = '80px';
-			div.style.float = 'left';
-			var input = document.createElement('input');
-			input.type = 'radio';
-			input.name = commentQuestion.id;
-			input.setAttribute('setvalue',optNode.name);
-			input.className = 'comment-radio';
-			div.appendChild(input);
-			this.inputs.appendChild(div);
-			
-			
-			div = document.createElement('div');
-			div.style.width = '80px';
-			div.style.float = 'left';
-			div.align = 'center';
-			var span = document.createElement('span');
-			span.textContent = optNode.text;
-			span.className = 'comment-radio-span';
-			div.appendChild(span);
-			this.span.appendChild(div);
-			this.options.push(input);
-		}
-		this.holder.appendChild(this.span);
-		this.holder.appendChild(this.inputs);
-		
-		this.exportXMLDOM = function(storePoint) {
-			var root = storePoint.parent.document.createElement('comment');
-			root.id = this.specification.id;
-			root.setAttribute('type',this.specification.type);
-			var question = document.createElement('question');
-			question.textContent = this.string.textContent;
-			var response = document.createElement('response');
-			var i=0;
-			while(this.options[i].checked == false) {
-				i++;
-				if (i >= this.options.length) {
-					break;
-				}
-			}
-			if (i >= this.options.length) {
-				response.textContent = 'null';
-			} else {
-				response.textContent = this.options[i].getAttribute('setvalue');
-				response.setAttribute('number',i);
-			}
-			console.log('Comment: '+question.textContent);
-			console.log('Response: '+response.textContent);
-			root.appendChild(question);
-			root.appendChild(response);
+
+        var optCount = commentQuestion.options.length;
+        for (var optNode of commentQuestion.options) {
+            var div = document.createElement('div');
+            div.style.width = '80px';
+            div.style.float = 'left';
+            var input = document.createElement('input');
+            input.type = 'radio';
+            input.name = commentQuestion.id;
+            input.setAttribute('setvalue', optNode.name);
+            input.className = 'comment-radio';
+            div.appendChild(input);
+            this.inputs.appendChild(div);
+
+
+            div = document.createElement('div');
+            div.style.width = '80px';
+            div.style.float = 'left';
+            div.align = 'center';
+            var span = document.createElement('span');
+            span.textContent = optNode.text;
+            span.className = 'comment-radio-span';
+            div.appendChild(span);
+            this.span.appendChild(div);
+            this.options.push(input);
+        }
+        this.holder.appendChild(this.span);
+        this.holder.appendChild(this.inputs);
+
+        this.exportXMLDOM = function (storePoint) {
+            var root = storePoint.parent.document.createElement('comment');
+            root.id = this.specification.id;
+            root.setAttribute('type', this.specification.type);
+            var question = document.createElement('question');
+            question.textContent = this.string.textContent;
+            var response = document.createElement('response');
+            var i = 0;
+            while (this.options[i].checked == false) {
+                i++;
+                if (i >= this.options.length) {
+                    break;
+                }
+            }
+            if (i >= this.options.length) {
+                response.textContent = 'null';
+            } else {
+                response.textContent = this.options[i].getAttribute('setvalue');
+                response.setAttribute('number', i);
+            }
+            console.log('Comment: ' + question.textContent);
+            console.log('Response: ' + response.textContent);
+            root.appendChild(question);
+            root.appendChild(response);
             storePoint.XMLDOM.appendChild(root);
-			return root;
-		};
-		this.resize = function()
-		{
-			var boxwidth = (window.innerWidth-100)/2;
-			if (boxwidth >= 600)
-			{
-				boxwidth = 600;
-			}
-			else if (boxwidth < 400)
-			{
-				boxwidth = 400;
-			}
-			this.holder.style.width = boxwidth+"px";
-			var text = this.holder.getElementsByClassName("comment-radio-span-holder")[0];
-			var options = this.holder.getElementsByClassName("comment-radio-inputs-holder")[0];
-			var optCount = options.childElementCount;
-			var spanMargin = Math.floor(((boxwidth-20-(optCount*80))/(optCount))/2)+'px';
-			var options = options.firstChild;
-			var text = text.firstChild;
-			options.style.marginRight = spanMargin;
-			options.style.marginLeft = spanMargin;
-			text.style.marginRight = spanMargin;
-			text.style.marginLeft = spanMargin;
-			while(options.nextSibling != undefined)
-			{
-				options = options.nextSibling;
-				text = text.nextSibling;
-				options.style.marginRight = spanMargin;
-				options.style.marginLeft = spanMargin;
-				text.style.marginRight = spanMargin;
-				text.style.marginLeft = spanMargin;
-			}
-		};
-		this.resize();
-	};
-	
-	this.checkboxBox = function(commentQuestion) {
-		this.specification = commentQuestion;
-		// Create document objects to hold the comment boxes
-		this.holder = document.createElement('div');
-		this.holder.className = 'comment-div';
-		// Create a string next to each comment asking for a comment
-		this.string = document.createElement('span');
-		this.string.innerHTML = commentQuestion.statement;
-		var br = document.createElement('br');
-		// Add to the holder.
-		this.holder.appendChild(this.string);
-		this.holder.appendChild(br);
-		this.options = [];
-		this.inputs = document.createElement('div');
-		this.span = document.createElement('div');
-		this.inputs.align = 'center';
-		this.inputs.style.marginLeft = '12px';
+            return root;
+        };
+        this.resize = function () {
+            var boxwidth = (window.innerWidth - 100) / 2;
+            if (boxwidth >= 600) {
+                boxwidth = 600;
+            } else if (boxwidth < 400) {
+                boxwidth = 400;
+            }
+            this.holder.style.width = boxwidth + "px";
+            var text = this.holder.getElementsByClassName("comment-radio-span-holder")[0];
+            var options = this.holder.getElementsByClassName("comment-radio-inputs-holder")[0];
+            var optCount = options.childElementCount;
+            var spanMargin = Math.floor(((boxwidth - 20 - (optCount * 80)) / (optCount)) / 2) + 'px';
+            var options = options.firstChild;
+            var text = text.firstChild;
+            options.style.marginRight = spanMargin;
+            options.style.marginLeft = spanMargin;
+            text.style.marginRight = spanMargin;
+            text.style.marginLeft = spanMargin;
+            while (options.nextSibling != undefined) {
+                options = options.nextSibling;
+                text = text.nextSibling;
+                options.style.marginRight = spanMargin;
+                options.style.marginLeft = spanMargin;
+                text.style.marginRight = spanMargin;
+                text.style.marginLeft = spanMargin;
+            }
+        };
+        this.resize();
+    };
+
+    this.checkboxBox = function (commentQuestion) {
+        this.specification = commentQuestion;
+        // Create document objects to hold the comment boxes
+        this.holder = document.createElement('div');
+        this.holder.className = 'comment-div';
+        // Create a string next to each comment asking for a comment
+        this.string = document.createElement('span');
+        this.string.innerHTML = commentQuestion.statement;
+        var br = document.createElement('br');
+        // Add to the holder.
+        this.holder.appendChild(this.string);
+        this.holder.appendChild(br);
+        this.options = [];
+        this.inputs = document.createElement('div');
+        this.span = document.createElement('div');
+        this.inputs.align = 'center';
+        this.inputs.style.marginLeft = '12px';
         this.inputs.className = "comment-checkbox-inputs-holder";
-		this.span.style.marginLeft = '12px';
-		this.span.align = 'center';
-		this.span.style.marginTop = '15px';
+        this.span.style.marginLeft = '12px';
+        this.span.align = 'center';
+        this.span.style.marginTop = '15px';
         this.span.className = "comment-checkbox-span-holder";
-		
-		var optCount = commentQuestion.options.length;
-		for (var i=0; i<optCount; i++)
-		{
-			var div = document.createElement('div');
-			div.style.width = '80px';
-			div.style.float = 'left';
-			var input = document.createElement('input');
-			input.type = 'checkbox';
-			input.name = commentQuestion.id;
-			input.setAttribute('setvalue',commentQuestion.options[i].name);
-			input.className = 'comment-radio';
-			div.appendChild(input);
-			this.inputs.appendChild(div);
-			
-			
-			div = document.createElement('div');
-			div.style.width = '80px';
-			div.style.float = 'left';
-			div.align = 'center';
-			var span = document.createElement('span');
-			span.textContent = commentQuestion.options[i].text;
-			span.className = 'comment-radio-span';
-			div.appendChild(span);
-			this.span.appendChild(div);
-			this.options.push(input);
-		}
-		this.holder.appendChild(this.span);
-		this.holder.appendChild(this.inputs);
-		
-		this.exportXMLDOM = function(storePoint) {
-			var root = storePoint.parent.document.createElement('comment');
-			root.id = this.specification.id;
-			root.setAttribute('type',this.specification.type);
-			var question = document.createElement('question');
-			question.textContent = this.string.textContent;
-			root.appendChild(question);
-			console.log('Comment: '+question.textContent);
-			for (var i=0; i<this.options.length; i++) {
-				var response = document.createElement('response');
-				response.textContent = this.options[i].checked;
-				response.setAttribute('name',this.options[i].getAttribute('setvalue'));
-				root.appendChild(response);
-				console.log('Response '+response.getAttribute('name') +': '+response.textContent);
-			}
+
+        var optCount = commentQuestion.options.length;
+        for (var i = 0; i < optCount; i++) {
+            var div = document.createElement('div');
+            div.style.width = '80px';
+            div.style.float = 'left';
+            var input = document.createElement('input');
+            input.type = 'checkbox';
+            input.name = commentQuestion.id;
+            input.setAttribute('setvalue', commentQuestion.options[i].name);
+            input.className = 'comment-radio';
+            div.appendChild(input);
+            this.inputs.appendChild(div);
+
+
+            div = document.createElement('div');
+            div.style.width = '80px';
+            div.style.float = 'left';
+            div.align = 'center';
+            var span = document.createElement('span');
+            span.textContent = commentQuestion.options[i].text;
+            span.className = 'comment-radio-span';
+            div.appendChild(span);
+            this.span.appendChild(div);
+            this.options.push(input);
+        }
+        this.holder.appendChild(this.span);
+        this.holder.appendChild(this.inputs);
+
+        this.exportXMLDOM = function (storePoint) {
+            var root = storePoint.parent.document.createElement('comment');
+            root.id = this.specification.id;
+            root.setAttribute('type', this.specification.type);
+            var question = document.createElement('question');
+            question.textContent = this.string.textContent;
+            root.appendChild(question);
+            console.log('Comment: ' + question.textContent);
+            for (var i = 0; i < this.options.length; i++) {
+                var response = document.createElement('response');
+                response.textContent = this.options[i].checked;
+                response.setAttribute('name', this.options[i].getAttribute('setvalue'));
+                root.appendChild(response);
+                console.log('Response ' + response.getAttribute('name') + ': ' + response.textContent);
+            }
             storePoint.XMLDOM.appendChild(root);
-			return root;
-		};
-		this.resize = function()
-		{
-			var boxwidth = (window.innerWidth-100)/2;
-			if (boxwidth >= 600)
-			{
-				boxwidth = 600;
-			}
-			else if (boxwidth < 400)
-			{
-				boxwidth = 400;
-			}
-			this.holder.style.width = boxwidth+"px";
-			var text = this.holder.getElementsByClassName("comment-checkbox-span-holder")[0];
-			var options = this.holder.getElementsByClassName("comment-checkbox-inputs-holder")[0];
-			var optCount = options.childElementCount;
-			var spanMargin = Math.floor(((boxwidth-20-(optCount*80))/(optCount))/2)+'px';
-			var options = options.firstChild;
-			var text = text.firstChild;
-			options.style.marginRight = spanMargin;
-			options.style.marginLeft = spanMargin;
-			text.style.marginRight = spanMargin;
-			text.style.marginLeft = spanMargin;
-			while(options.nextSibling != undefined)
-			{
-				options = options.nextSibling;
-				text = text.nextSibling;
-				options.style.marginRight = spanMargin;
-				options.style.marginLeft = spanMargin;
-				text.style.marginRight = spanMargin;
-				text.style.marginLeft = spanMargin;
-			}
-		};
-		this.resize();
-	};
-	
-	this.createCommentQuestion = function(element) {
-		var node;
-		if (element.type == 'question') {
-			node = new this.commentBox(element);
-		} else if (element.type == 'radio') {
-			node = new this.radioBox(element);
-		} else if (element.type == 'checkbox') {
-			node = new this.checkboxBox(element);
-		}
-		this.commentQuestions.push(node);
-		return node;
-	};
-	
-	this.deleteCommentQuestions = function()
-	{
-		this.commentQuestions = [];
-	};
-    
-    this.outsideReferenceDOM = function(audioObject,index,inject)
-    {
+            return root;
+        };
+        this.resize = function () {
+            var boxwidth = (window.innerWidth - 100) / 2;
+            if (boxwidth >= 600) {
+                boxwidth = 600;
+            } else if (boxwidth < 400) {
+                boxwidth = 400;
+            }
+            this.holder.style.width = boxwidth + "px";
+            var text = this.holder.getElementsByClassName("comment-checkbox-span-holder")[0];
+            var options = this.holder.getElementsByClassName("comment-checkbox-inputs-holder")[0];
+            var optCount = options.childElementCount;
+            var spanMargin = Math.floor(((boxwidth - 20 - (optCount * 80)) / (optCount)) / 2) + 'px';
+            var options = options.firstChild;
+            var text = text.firstChild;
+            options.style.marginRight = spanMargin;
+            options.style.marginLeft = spanMargin;
+            text.style.marginRight = spanMargin;
+            text.style.marginLeft = spanMargin;
+            while (options.nextSibling != undefined) {
+                options = options.nextSibling;
+                text = text.nextSibling;
+                options.style.marginRight = spanMargin;
+                options.style.marginLeft = spanMargin;
+                text.style.marginRight = spanMargin;
+                text.style.marginLeft = spanMargin;
+            }
+        };
+        this.resize();
+    };
+
+    this.createCommentQuestion = function (element) {
+        var node;
+        if (element.type == 'question') {
+            node = new this.commentBox(element);
+        } else if (element.type == 'radio') {
+            node = new this.radioBox(element);
+        } else if (element.type == 'checkbox') {
+            node = new this.checkboxBox(element);
+        }
+        this.commentQuestions.push(node);
+        return node;
+    };
+
+    this.deleteCommentQuestions = function () {
+        this.commentQuestions = [];
+    };
+
+    this.outsideReferenceDOM = function (audioObject, index, inject) {
         this.parent = audioObject;
         this.outsideReferenceHolder = document.createElement('button');
         this.outsideReferenceHolder.className = 'outside-reference';
-        this.outsideReferenceHolder.setAttribute('track-id',index);
+        this.outsideReferenceHolder.setAttribute('track-id', index);
         this.outsideReferenceHolder.textContent = this.parent.specification.label || "Reference";
         this.outsideReferenceHolder.disabled = true;
 
-        this.outsideReferenceHolder.onclick = function(event)
-        {
+        this.outsideReferenceHolder.onclick = function (event) {
             audioEngineContext.play(event.currentTarget.getAttribute('track-id'));
         };
         inject.appendChild(this.outsideReferenceHolder);
-        this.enable = function()
-        {
-            if (this.parent.state == 1)
-            {
+        this.enable = function () {
+            if (this.parent.state == 1) {
                 this.outsideReferenceHolder.disabled = false;
             }
         };
-        this.updateLoading = function(progress)
-        {
-            if (progress != 100)
-            {
+        this.updateLoading = function (progress) {
+            if (progress != 100) {
                 progress = String(progress);
                 progress = progress.split('.')[0];
-                this.outsideReferenceHolder.textContent = progress+'%';
+                this.outsideReferenceHolder.textContent = progress + '%';
             } else {
                 this.outsideReferenceHolder.textContent = this.parent.specification.label || "Reference";
             }
         };
-        this.startPlayback = function()
-        {
+        this.startPlayback = function () {
             // Called when playback has begun
             $('.track-slider').removeClass('track-slider-playing');
             $('.comment-div').removeClass('comment-box-playing');
             this.outsideReferenceHolder.style.backgroundColor = "#FDD";
         };
-        this.stopPlayback = function()
-        {
+        this.stopPlayback = function () {
             // Called when playback has stopped. This gets called even if playback never started!
             this.outsideReferenceHolder.style.backgroundColor = "";
         };
-        this.exportXMLDOM = function(audioObject)
-        {
+        this.exportXMLDOM = function (audioObject) {
             return null;
         };
-        this.getValue = function()
-        {
+        this.getValue = function () {
             return 0;
         };
-        this.getPresentedId = function()
-        {
+        this.getPresentedId = function () {
             return this.parent.specification.label || "Reference";
         };
-        this.canMove = function()
-        {
+        this.canMove = function () {
             return false;
         };
-        this.error = function() {
-                // audioObject has an error!!
+        this.error = function () {
+            // audioObject has an error!!
             this.outsideReferenceHolder.textContent = "Error";
             this.outsideReferenceHolder.style.backgroundColor = "#F00";
         }
     }
-	
-	this.playhead = new function()
-	{
-		this.object = document.createElement('div');
-		this.object.className = 'playhead';
-		this.object.align = 'left';
-		var curTime = document.createElement('div');
-		curTime.style.width = '50px';
-		this.curTimeSpan = document.createElement('span');
-		this.curTimeSpan.textContent = '00:00';
-		curTime.appendChild(this.curTimeSpan);
-		this.object.appendChild(curTime);
-		this.scrubberTrack = document.createElement('div');
-		this.scrubberTrack.className = 'playhead-scrub-track';
-		
-		this.scrubberHead = document.createElement('div');
-		this.scrubberHead.id = 'playhead-scrubber';
-		this.scrubberTrack.appendChild(this.scrubberHead);
-		this.object.appendChild(this.scrubberTrack);
-		
-		this.timePerPixel = 0;
-		this.maxTime = 0;
-		
-		this.playbackObject;
-		
-		this.setTimePerPixel = function(audioObject) {
-			//maxTime must be in seconds
-			this.playbackObject = audioObject;
-			this.maxTime = audioObject.buffer.buffer.duration;
-			var width = 490; //500 - 10, 5 each side of the tracker head
-			this.timePerPixel = this.maxTime/490;
-			if (this.maxTime < 60) {
-				this.curTimeSpan.textContent = '0.00';
-			} else {
-				this.curTimeSpan.textContent = '00:00';
-			}
-		};
-		
-		this.update = function() {
-			// Update the playhead position, startPlay must be called
-			if (this.timePerPixel > 0) {
-				var time = this.playbackObject.getCurrentPosition();
-				if (time > 0 && time < this.maxTime) {
-					var width = 490;
-					var pix = Math.floor(time/this.timePerPixel);
-					this.scrubberHead.style.left = pix+'px';
-					if (this.maxTime > 60.0) {
-						var secs = time%60;
-						var mins = Math.floor((time-secs)/60);
-						secs = secs.toString();
-						secs = secs.substr(0,2);
-						mins = mins.toString();
-						this.curTimeSpan.textContent = mins+':'+secs;
-					} else {
-						time = time.toString();
-						this.curTimeSpan.textContent = time.substr(0,4);
-					}
-				} else {
-					this.scrubberHead.style.left = '0px';
-					if (this.maxTime < 60) {
-						this.curTimeSpan.textContent = '0.00';
-					} else {
-						this.curTimeSpan.textContent = '00:00';
-					}
-				}
-			}
-		};
-		
-		this.interval = undefined;
-		
-		this.start = function() {
-			if (this.playbackObject != undefined && this.interval == undefined) {
-				if (this.maxTime < 60) {
-					this.interval = setInterval(function(){interfaceContext.playhead.update();},10);
-				} else {
-					this.interval = setInterval(function(){interfaceContext.playhead.update();},100);
-				}
-			}
-		};
-		this.stop = function() {
-			clearInterval(this.interval);
-			this.interval = undefined;
+
+    this.playhead = new function () {
+        this.object = document.createElement('div');
+        this.object.className = 'playhead';
+        this.object.align = 'left';
+        var curTime = document.createElement('div');
+        curTime.style.width = '50px';
+        this.curTimeSpan = document.createElement('span');
+        this.curTimeSpan.textContent = '00:00';
+        curTime.appendChild(this.curTimeSpan);
+        this.object.appendChild(curTime);
+        this.scrubberTrack = document.createElement('div');
+        this.scrubberTrack.className = 'playhead-scrub-track';
+
+        this.scrubberHead = document.createElement('div');
+        this.scrubberHead.id = 'playhead-scrubber';
+        this.scrubberTrack.appendChild(this.scrubberHead);
+        this.object.appendChild(this.scrubberTrack);
+
+        this.timePerPixel = 0;
+        this.maxTime = 0;
+
+        this.playbackObject;
+
+        this.setTimePerPixel = function (audioObject) {
+            //maxTime must be in seconds
+            this.playbackObject = audioObject;
+            this.maxTime = audioObject.buffer.buffer.duration;
+            var width = 490; //500 - 10, 5 each side of the tracker head
+            this.timePerPixel = this.maxTime / 490;
+            if (this.maxTime < 60) {
+                this.curTimeSpan.textContent = '0.00';
+            } else {
+                this.curTimeSpan.textContent = '00:00';
+            }
+        };
+
+        this.update = function () {
+            // Update the playhead position, startPlay must be called
+            if (this.timePerPixel > 0) {
+                var time = this.playbackObject.getCurrentPosition();
+                if (time > 0 && time < this.maxTime) {
+                    var width = 490;
+                    var pix = Math.floor(time / this.timePerPixel);
+                    this.scrubberHead.style.left = pix + 'px';
+                    if (this.maxTime > 60.0) {
+                        var secs = time % 60;
+                        var mins = Math.floor((time - secs) / 60);
+                        secs = secs.toString();
+                        secs = secs.substr(0, 2);
+                        mins = mins.toString();
+                        this.curTimeSpan.textContent = mins + ':' + secs;
+                    } else {
+                        time = time.toString();
+                        this.curTimeSpan.textContent = time.substr(0, 4);
+                    }
+                } else {
+                    this.scrubberHead.style.left = '0px';
+                    if (this.maxTime < 60) {
+                        this.curTimeSpan.textContent = '0.00';
+                    } else {
+                        this.curTimeSpan.textContent = '00:00';
+                    }
+                }
+            }
+        };
+
+        this.interval = undefined;
+
+        this.start = function () {
+            if (this.playbackObject != undefined && this.interval == undefined) {
+                if (this.maxTime < 60) {
+                    this.interval = setInterval(function () {
+                        interfaceContext.playhead.update();
+                    }, 10);
+                } else {
+                    this.interval = setInterval(function () {
+                        interfaceContext.playhead.update();
+                    }, 100);
+                }
+            }
+        };
+        this.stop = function () {
+            clearInterval(this.interval);
+            this.interval = undefined;
             this.scrubberHead.style.left = '0px';
-			if (this.maxTime < 60) {
-				this.curTimeSpan.textContent = '0.00';
-			} else {
-				this.curTimeSpan.textContent = '00:00';
-			}
-		};
-	};
-    
-    this.volume = new function()
-    {
+            if (this.maxTime < 60) {
+                this.curTimeSpan.textContent = '0.00';
+            } else {
+                this.curTimeSpan.textContent = '00:00';
+            }
+        };
+    };
+
+    this.volume = new function () {
         // An in-built volume module which can be viewed on page
         // Includes trackers on page-by-page data
         // Volume does NOT reset to 0dB on each page load
@@ -2845,48 +2776,44 @@
         this.valueText = document.createElement('span');
         this.valueText.id = 'master-volume-feedback';
         this.valueText.textContent = '0dB';
-        
+
         this.slider.min = -60;
         this.slider.max = 12;
         this.slider.value = 0;
         this.slider.step = 1;
-        this.slider.onmousemove = function(event)
-        {
+        this.slider.onmousemove = function (event) {
             interfaceContext.volume.valueDB = event.currentTarget.value;
             interfaceContext.volume.valueLin = decibelToLinear(interfaceContext.volume.valueDB);
-            interfaceContext.volume.valueText.textContent = interfaceContext.volume.valueDB+'dB';
+            interfaceContext.volume.valueText.textContent = interfaceContext.volume.valueDB + 'dB';
             audioEngineContext.outputGain.gain.value = interfaceContext.volume.valueLin;
         }
-        this.slider.onmouseup = function(event)
-        {
+        this.slider.onmouseup = function (event) {
             var storePoint = testState.currentStore.XMLDOM.getElementsByTagName('metric')[0].getAllElementsByName('volumeTracker');
-            if (storePoint.length == 0)
-            {
+            if (storePoint.length == 0) {
                 storePoint = storage.document.createElement('metricresult');
-                storePoint.setAttribute('name','volumeTracker');
+                storePoint.setAttribute('name', 'volumeTracker');
                 testState.currentStore.XMLDOM.getElementsByTagName('metric')[0].appendChild(storePoint);
-            }
-            else {
+            } else {
                 storePoint = storePoint[0];
             }
             var node = storage.document.createElement('movement');
-            node.setAttribute('test-time',audioEngineContext.timer.getTestTime());
-            node.setAttribute('volume',interfaceContext.volume.valueDB);
-            node.setAttribute('format','dBFS');
+            node.setAttribute('test-time', audioEngineContext.timer.getTestTime());
+            node.setAttribute('volume', interfaceContext.volume.valueDB);
+            node.setAttribute('format', 'dBFS');
             storePoint.appendChild(node);
         }
-        
+
         var title = document.createElement('div');
         title.innerHTML = '<span>Master Volume Control</span>';
         title.style.fontSize = '0.75em';
         title.style.width = "100%";
         title.align = 'center';
         this.root.appendChild(title);
-        
+
         this.root.appendChild(this.slider);
         this.root.appendChild(this.valueText);
-        
-        this.resize = function(event) {
+
+        this.resize = function (event) {
             if (window.innerWidth < 1000) {
                 this.object.className = "master-volume-holder-inline"
             } else {
@@ -2894,21 +2821,21 @@
             }
         }
     }
-    
+
     this.calibrationModuleObject = null;
-    this.calibrationModule = function() {
+    this.calibrationModule = function () {
         // This creates an on-page calibration module
         this.storeDOM = storage.document.createElement("calibration");
         storage.root.appendChild(this.storeDOM);
         // The calibration is a fixed state module
         this.calibrationNodes = [];
         this.holder = null;
-        this.build = function(inject) {
+        this.build = function (inject) {
             var f0 = 62.5;
             this.holder = document.createElement("div");
             this.holder.className = "calibration-holder";
             this.calibrationNodes = [];
-            while(f0 < 20000) {
+            while (f0 < 20000) {
                 var obj = {
                     root: document.createElement("div"),
                     input: document.createElement("input"),
@@ -2916,8 +2843,8 @@
                     gain: audioContext.createGain(),
                     f: f0,
                     parent: this,
-                    handleEvent: function(event) {
-                        switch(event.type) {
+                    handleEvent: function (event) {
+                        switch (event.type) {
                             case "mouseenter":
                                 this.oscillator.start(0);
                                 break;
@@ -2928,7 +2855,7 @@
                                 this.oscillator.frequency.value = this.f;
                                 break;
                             case "mousemove":
-                                var value = Math.pow(10,this.input.value/20);
+                                var value = Math.pow(10, this.input.value / 20);
                                 if (this.f == 1000) {
                                     audioEngineContext.outputGain.gain.value = value;
                                     interfaceContext.volume.slider.value = this.input.value;
@@ -2938,7 +2865,7 @@
                                 break;
                         }
                     },
-                    disconnect: function() {
+                    disconnect: function () {
                         this.gain.disconnect();
                     }
                 }
@@ -2946,23 +2873,23 @@
                 obj.root.appendChild(obj.input);
                 obj.oscillator.connect(obj.gain);
                 obj.gain.connect(audioEngineContext.outputGain);
-                obj.gain.gain.value = Math.random()*2;
+                obj.gain.gain.value = Math.random() * 2;
                 obj.input.value = obj.gain.gain.value;
-                obj.input.setAttribute('orient','vertical');
+                obj.input.setAttribute('orient', 'vertical');
                 obj.input.type = "range";
                 obj.input.min = -6;
                 obj.input.max = 6;
                 obj.input.step = 0.25;
                 if (f0 != 1000) {
-                    obj.input.value = (Math.random()*12)-6;
+                    obj.input.value = (Math.random() * 12) - 6;
                 } else {
                     obj.input.value = 0;
-                    obj.root.style.backgroundColor="rgb(255,125,125)";
+                    obj.root.style.backgroundColor = "rgb(255,125,125)";
                 }
-                obj.input.addEventListener("mousemove",obj);
-                obj.input.addEventListener("mouseenter",obj);
-                obj.input.addEventListener("mouseleave",obj);
-                obj.gain.gain.value = Math.pow(10,obj.input.value/20);
+                obj.input.addEventListener("mousemove", obj);
+                obj.input.addEventListener("mouseenter", obj);
+                obj.input.addEventListener("mouseleave", obj);
+                obj.gain.gain.value = Math.pow(10, obj.input.value / 20);
                 obj.oscillator.frequency.value = f0;
                 this.calibrationNodes.push(obj);
                 this.holder.appendChild(obj.root);
@@ -2970,175 +2897,148 @@
             }
             inject.appendChild(this.holder);
         }
-        this.collect = function() {
+        this.collect = function () {
             for (var obj of this.calibrationNodes) {
                 var node = storage.document.createElement("calibrationresult");
-                node.setAttribute("frequency",obj.f);
-                node.setAttribute("range-min",obj.input.min);
-                node.setAttribute("range-max",obj.input.max);
-                node.setAttribute("gain-lin",obj.gain.gain.value);
+                node.setAttribute("frequency", obj.f);
+                node.setAttribute("range-min", obj.input.min);
+                node.setAttribute("range-max", obj.input.max);
+                node.setAttribute("gain-lin", obj.gain.gain.value);
                 this.storeDOM.appendChild(node);
             }
         }
     }
-    
-    
-	// Global Checkers
-	// These functions will help enforce the checkers
-	this.checkHiddenAnchor = function()
-	{
-		for (var ao of audioEngineContext.audioObjects)
-		{
-			if (ao.specification.type == "anchor")
-			{
-				if (ao.interfaceDOM.getValue() > (ao.specification.marker/100) && ao.specification.marker > 0) {
-					// Anchor is not set below
-					console.log('Anchor node not below marker value');
-					interfaceContext.lightbox.post("Message",'Please keep listening');
+
+
+    // Global Checkers
+    // These functions will help enforce the checkers
+    this.checkHiddenAnchor = function () {
+        for (var ao of audioEngineContext.audioObjects) {
+            if (ao.specification.type == "anchor") {
+                if (ao.interfaceDOM.getValue() > (ao.specification.marker / 100) && ao.specification.marker > 0) {
+                    // Anchor is not set below
+                    console.log('Anchor node not below marker value');
+                    interfaceContext.lightbox.post("Message", 'Please keep listening');
                     this.storeErrorNode('Anchor node not below marker value');
-					return false;
-				}
-			}
-		}
-		return true;
-	};
-	
-	this.checkHiddenReference = function()
-	{
-		for (var ao of audioEngineContext.audioObjects)
-		{
-			if (ao.specification.type == "reference")
-			{
-				if (ao.interfaceDOM.getValue() < (ao.specification.marker/100) && ao.specification.marker > 0) {
-					// Anchor is not set below
-					console.log('Reference node not above marker value');
+                    return false;
+                }
+            }
+        }
+        return true;
+    };
+
+    this.checkHiddenReference = function () {
+        for (var ao of audioEngineContext.audioObjects) {
+            if (ao.specification.type == "reference") {
+                if (ao.interfaceDOM.getValue() < (ao.specification.marker / 100) && ao.specification.marker > 0) {
+                    // Anchor is not set below
+                    console.log('Reference node not above marker value');
                     this.storeErrorNode('Reference node not above marker value');
-					interfaceContext.lightbox.post("Message",'Please keep listening');
-					return false;
-				}
-			}
-		}
-		return true;
-	};
-	
-	this.checkFragmentsFullyPlayed = function ()
-	{
-		// Checks the entire file has been played back
-		// NOTE ! This will return true IF playback is Looped!!!
-		if (audioEngineContext.loopPlayback)
-		{
-			console.log("WARNING - Looped source: Cannot check fragments are fully played");
-			return true;
-		}
-		var check_pass = true;
-		var error_obj = [];
-		for (var i = 0; i<audioEngineContext.audioObjects.length; i++)
-		{
-			var object = audioEngineContext.audioObjects[i];
-			var time = object.buffer.buffer.duration;
-			var metric = object.metric;
-			var passed = false;
-			for (var j=0; j<metric.listenTracker.length; j++)
-			{
-				var bt = metric.listenTracker[j].getElementsByTagName('testtime');
-				var start_time = Number(bt[0].getAttribute('start'));
-				var stop_time = Number(bt[0].getAttribute('stop'));
-				var delta = stop_time - start_time;
-				if (delta >= time)
-				{
-					passed = true;
-					break;
-				}
-			}
-			if (passed == false)
-			{
-				check_pass = false;
-				console.log("Continue listening to track-"+object.interfaceDOM.getPresentedId());
-				error_obj.push(object.interfaceDOM.getPresentedId());
-			}
-		}
-		if (check_pass == false)
-		{
-			var str_start = "You have not completely listened to fragments ";
-			for (var i=0; i<error_obj.length; i++)
-			{
-				str_start += error_obj[i];
-				if (i != error_obj.length-1)
-				{
-					str_start += ', ';
-				}
-			}
-			str_start += ". Please keep listening";
-			console.log("[ALERT]: "+str_start);
-            this.storeErrorNode("[ALERT]: "+str_start);
-			interfaceContext.lightbox.post("Error",str_start);
+                    interfaceContext.lightbox.post("Message", 'Please keep listening');
+                    return false;
+                }
+            }
+        }
+        return true;
+    };
+
+    this.checkFragmentsFullyPlayed = function () {
+        // Checks the entire file has been played back
+        // NOTE ! This will return true IF playback is Looped!!!
+        if (audioEngineContext.loopPlayback) {
+            console.log("WARNING - Looped source: Cannot check fragments are fully played");
+            return true;
+        }
+        var check_pass = true;
+        var error_obj = [];
+        for (var i = 0; i < audioEngineContext.audioObjects.length; i++) {
+            var object = audioEngineContext.audioObjects[i];
+            var time = object.buffer.buffer.duration;
+            var metric = object.metric;
+            var passed = false;
+            for (var j = 0; j < metric.listenTracker.length; j++) {
+                var bt = metric.listenTracker[j].getElementsByTagName('testtime');
+                var start_time = Number(bt[0].getAttribute('start'));
+                var stop_time = Number(bt[0].getAttribute('stop'));
+                var delta = stop_time - start_time;
+                if (delta >= time) {
+                    passed = true;
+                    break;
+                }
+            }
+            if (passed == false) {
+                check_pass = false;
+                console.log("Continue listening to track-" + object.interfaceDOM.getPresentedId());
+                error_obj.push(object.interfaceDOM.getPresentedId());
+            }
+        }
+        if (check_pass == false) {
+            var str_start = "You have not completely listened to fragments ";
+            for (var i = 0; i < error_obj.length; i++) {
+                str_start += error_obj[i];
+                if (i != error_obj.length - 1) {
+                    str_start += ', ';
+                }
+            }
+            str_start += ". Please keep listening";
+            console.log("[ALERT]: " + str_start);
+            this.storeErrorNode("[ALERT]: " + str_start);
+            interfaceContext.lightbox.post("Error", str_start);
             return false;
-		}
+        }
         return true;
-	};
-	this.checkAllMoved = function()
-	{
-		var str = "You have not moved ";
-		var failed = [];
-		for (var ao of audioEngineContext.audioObjects)
-		{
-			if(ao.metric.wasMoved == false && ao.interfaceDOM.canMove() == true)
-			{
-				failed.push(ao.interfaceDOM.getPresentedId());
-			}
-		}
-		if (failed.length == 0)
-		{
-			return true;
-		} else if (failed.length == 1)
-		{
-			str += 'track '+failed[0];
-		} else {
-			str += 'tracks ';
-			for (var i=0; i<failed.length-1; i++)
-			{
-				str += failed[i]+', ';
-			}
-			str += 'and '+failed[i];
-		}
-		str +='.';
-		interfaceContext.lightbox.post("Error",str);
-		console.log(str);
+    };
+    this.checkAllMoved = function () {
+        var str = "You have not moved ";
+        var failed = [];
+        for (var ao of audioEngineContext.audioObjects) {
+            if (ao.metric.wasMoved == false && ao.interfaceDOM.canMove() == true) {
+                failed.push(ao.interfaceDOM.getPresentedId());
+            }
+        }
+        if (failed.length == 0) {
+            return true;
+        } else if (failed.length == 1) {
+            str += 'track ' + failed[0];
+        } else {
+            str += 'tracks ';
+            for (var i = 0; i < failed.length - 1; i++) {
+                str += failed[i] + ', ';
+            }
+            str += 'and ' + failed[i];
+        }
+        str += '.';
+        interfaceContext.lightbox.post("Error", str);
+        console.log(str);
         this.storeErrorNode(str);
-		return false;
-	};
-	this.checkAllPlayed = function()
-	{
-		var str = "You have not played ";
-		var failed = [];
-		for (var ao of audioEngineContext.audioObjects)
-		{
-			if(ao.metric.wasListenedTo == false)
-			{
-				failed.push(ao.interfaceDOM.getPresentedId());
-			}
-		}
-		if (failed.length == 0)
-		{
-			return true;
-		} else if (failed.length == 1)
-		{
-			str += 'track '+failed[0];
-		} else {
-			str += 'tracks ';
-			for (var i=0; i<failed.length-1; i++)
-			{
-				str += failed[i]+', ';
-			}
-			str += 'and '+failed[i];
-		}
-		str +='.';
-		interfaceContext.lightbox.post("Error",str);
-		console.log(str);
+        return false;
+    };
+    this.checkAllPlayed = function () {
+        var str = "You have not played ";
+        var failed = [];
+        for (var ao of audioEngineContext.audioObjects) {
+            if (ao.metric.wasListenedTo == false) {
+                failed.push(ao.interfaceDOM.getPresentedId());
+            }
+        }
+        if (failed.length == 0) {
+            return true;
+        } else if (failed.length == 1) {
+            str += 'track ' + failed[0];
+        } else {
+            str += 'tracks ';
+            for (var i = 0; i < failed.length - 1; i++) {
+                str += failed[i] + ', ';
+            }
+            str += 'and ' + failed[i];
+        }
+        str += '.';
+        interfaceContext.lightbox.post("Error", str);
+        console.log(str);
         this.storeErrorNode(str);
-		return false;
-	};
-    this.checkScaleRange = function(min, max) {
+        return false;
+    };
+    this.checkScaleRange = function (min, max) {
         var page = testState.getCurrentTestPage();
         var audioObjects = audioEngineContext.audioObjects;
         var state = true;
@@ -3147,55 +3047,56 @@
         var maxRanking = -Infinity;
         for (var ao of audioObjects) {
             var rank = ao.interfaceDOM.getValue();
-            if (rank < minRanking) {minRanking = rank;}
-            if (rank > maxRanking) {maxRanking = rank;}
+            if (rank < minRanking) {
+                minRanking = rank;
+            }
+            if (rank > maxRanking) {
+                maxRanking = rank;
+            }
         }
-        if (minRanking*100 > min) {
-            str += "At least one fragment must be below the "+min+" mark.";
+        if (minRanking * 100 > min) {
+            str += "At least one fragment must be below the " + min + " mark.";
             state = false;
         }
-        if (maxRanking*100 < max) {
-            str += "At least one fragment must be above the "+max+" mark."
+        if (maxRanking * 100 < max) {
+            str += "At least one fragment must be above the " + max + " mark."
             state = false;
         }
         if (!state) {
             console.log(str);
             this.storeErrorNode(str);
-            interfaceContext.lightbox.post("Error",str);
+            interfaceContext.lightbox.post("Error", str);
         }
         return state;
     }
-    
-    this.storeErrorNode = function(errorMessage)
-    {
+
+    this.storeErrorNode = function (errorMessage) {
         var time = audioEngineContext.timer.getTestTime();
         var node = storage.document.createElement('error');
-        node.setAttribute('time',time);
+        node.setAttribute('time', time);
         node.textContent = errorMessage;
         testState.currentStore.XMLDOM.appendChild(node);
     };
 }
 
-function Storage()
-{
-	// Holds results in XML format until ready for collection
-	this.globalPreTest = null;
-	this.globalPostTest = null;
-	this.testPages = [];
-	this.document = null;
-	this.root = null;
-	this.state = 0;
-	
-	this.initialise = function(existingStore)
-	{
+function Storage() {
+    // Holds results in XML format until ready for collection
+    this.globalPreTest = null;
+    this.globalPostTest = null;
+    this.testPages = [];
+    this.document = null;
+    this.root = null;
+    this.state = 0;
+
+    this.initialise = function (existingStore) {
         if (existingStore == undefined) {
             // We need to get the sessionKey
             this.SessionKey.generateKey();
-            this.document = document.implementation.createDocument(null,"waetresult",null);
+            this.document = document.implementation.createDocument(null, "waetresult", null);
             this.root = this.document.childNodes[0];
             var projectDocument = specification.projectXML;
-            projectDocument.setAttribute('file-name',url);
-            projectDocument.setAttribute('url',qualifyURL(url));
+            projectDocument.setAttribute('file-name', url);
+            projectDocument.setAttribute('url', qualifyURL(url));
             this.root.appendChild(projectDocument);
             this.root.appendChild(interfaceContext.returnDateNode());
             this.root.appendChild(interfaceContext.returnNavigator());
@@ -3204,68 +3105,72 @@
             this.root = existingStore.firstChild;
             this.SessionKey.key = this.root.getAttribute("key");
         }
-        if (specification.preTest != undefined){this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest);}
-        if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);}
-	};
-    
+        if (specification.preTest != undefined) {
+            this.globalPreTest = new this.surveyNode(this, this.root, specification.preTest);
+        }
+        if (specification.postTest != undefined) {
+            this.globalPostTest = new this.surveyNode(this, this.root, specification.postTest);
+        }
+    };
+
     this.SessionKey = {
         key: null,
         request: new XMLHttpRequest(),
         parent: this,
-        handleEvent: function() {
+        handleEvent: function () {
             var parse = new DOMParser();
-            var xml = parse.parseFromString(this.request.response,"text/xml");
+            var xml = parse.parseFromString(this.request.response, "text/xml");
             var shouldGenerateKey = true;
             if (this.request.response.length == 0) {
                 console.log("Error: Server did not respond");
                 return;
             }
-            if(xml.getElementsByTagName("state").length > 0){
-				if (xml.getElementsByTagName("state")[0].textContent == "OK") {
-					this.key = xml.getAllElementsByTagName("key")[0].textContent;
-					this.parent.root.setAttribute("key",this.key);
-					this.parent.root.setAttribute("state","empty");
-					shouldGenerateKey = false;
-				}
-			}
-			if(shouldGenerateKey === true){
-				this.generateKey();
-			}
+            if (xml.getElementsByTagName("state").length > 0) {
+                if (xml.getElementsByTagName("state")[0].textContent == "OK") {
+                    this.key = xml.getAllElementsByTagName("key")[0].textContent;
+                    this.parent.root.setAttribute("key", this.key);
+                    this.parent.root.setAttribute("state", "empty");
+                    shouldGenerateKey = false;
+                }
+            }
+            if (shouldGenerateKey === true) {
+                this.generateKey();
+            }
         },
-        generateKey: function() {
+        generateKey: function () {
             var temp_key = randomString(32);
             var returnURL = "";
             if (typeof specification.projectReturn == "string") {
-                if (specification.projectReturn.substr(0,4) == "http") {
+                if (specification.projectReturn.substr(0, 4) == "http") {
                     returnURL = specification.projectReturn;
                 }
             }
-            this.request.open("GET",returnURL+"php/keygen.php?key="+temp_key,true);
-            this.request.addEventListener("load",this);
+            this.request.open("GET", returnURL + "php/keygen.php?key=" + temp_key, true);
+            this.request.addEventListener("load", this);
             this.request.send();
         },
-        update: function() {
+        update: function () {
             if (this.key == null) {
                 console.log("Cannot save as key == null");
                 return;
             }
-            this.parent.root.setAttribute("state","update");
+            this.parent.root.setAttribute("state", "update");
             var xmlhttp = new XMLHttpRequest();
             var returnURL = "";
             if (typeof specification.projectReturn == "string") {
-                if (specification.projectReturn.substr(0,4) == "http") {
+                if (specification.projectReturn.substr(0, 4) == "http") {
                     returnURL = specification.projectReturn;
                 }
             }
-            xmlhttp.open("POST",returnURL+"php/save.php?key="+this.key);
+            xmlhttp.open("POST", returnURL + "php/save.php?key=" + this.key);
             xmlhttp.setRequestHeader('Content-Type', 'text/xml');
-            xmlhttp.onerror = function(){
+            xmlhttp.onerror = function () {
                 console.log('Error updating file to server!');
             };
             var hold = document.createElement("div");
             var clone = this.parent.root.cloneNode(true);
             hold.appendChild(clone);
-            xmlhttp.onload = function() {
+            xmlhttp.onload = function () {
                 if (this.status >= 300) {
                     console.log("WARNING - Could not update at this time");
                 } else {
@@ -3274,159 +3179,153 @@
                     var response = xmlDoc.getElementsByTagName('response')[0];
                     if (response.getAttribute("state") == "OK") {
                         var file = response.getElementsByTagName("file")[0];
-                        console.log("Intermediate save: OK, written "+file.getAttribute("bytes")+"B");
+                        console.log("Intermediate save: OK, written " + file.getAttribute("bytes") + "B");
                     } else {
                         var message = response.getElementsByTagName("message");
-                        console.log("Intermediate save: Error! "+message.textContent);
+                        console.log("Intermediate save: Error! " + message.textContent);
                     }
                 }
             }
             xmlhttp.send([hold.innerHTML]);
         }
     }
-	
-	this.createTestPageStore = function(specification)
-	{
-		var store = new this.pageNode(this,specification);
-		this.testPages.push(store);
-		return this.testPages[this.testPages.length-1];
-	};
-	
-	this.surveyNode = function(parent,root,specification)
-	{
-		this.specification = specification;
-		this.parent = parent;
+
+    this.createTestPageStore = function (specification) {
+        var store = new this.pageNode(this, specification);
+        this.testPages.push(store);
+        return this.testPages[this.testPages.length - 1];
+    };
+
+    this.surveyNode = function (parent, root, specification) {
+        this.specification = specification;
+        this.parent = parent;
         this.state = "empty";
-		this.XMLDOM = this.parent.document.createElement('survey');
-		this.XMLDOM.setAttribute('location',this.specification.location);
-        this.XMLDOM.setAttribute("state",this.state);
-		for (var optNode of this.specification.options)
-		{
-			if (optNode.type != 'statement')
-			{
-				var node = this.parent.document.createElement('surveyresult');
-				node.setAttribute("ref",optNode.id);
-				node.setAttribute('type',optNode.type);
-				this.XMLDOM.appendChild(node);
-			}
-		}
-		root.appendChild(this.XMLDOM);
-		
-		this.postResult = function(node)
-		{
-			// From popup: node is the popupOption node containing both spec. and results
-			// ID is the position
-			if (node.specification.type == 'statement'){return;}
-			var surveyresult = this.XMLDOM.firstChild;
-            while(surveyresult != null) {
-                if (surveyresult.getAttribute("ref") == node.specification.id)
-                {
+        this.XMLDOM = this.parent.document.createElement('survey');
+        this.XMLDOM.setAttribute('location', this.specification.location);
+        this.XMLDOM.setAttribute("state", this.state);
+        for (var optNode of this.specification.options) {
+            if (optNode.type != 'statement') {
+                var node = this.parent.document.createElement('surveyresult');
+                node.setAttribute("ref", optNode.id);
+                node.setAttribute('type', optNode.type);
+                this.XMLDOM.appendChild(node);
+            }
+        }
+        root.appendChild(this.XMLDOM);
+
+        this.postResult = function (node) {
+            // From popup: node is the popupOption node containing both spec. and results
+            // ID is the position
+            if (node.specification.type == 'statement') {
+                return;
+            }
+            var surveyresult = this.XMLDOM.firstChild;
+            while (surveyresult != null) {
+                if (surveyresult.getAttribute("ref") == node.specification.id) {
                     break;
                 }
                 surveyresult = surveyresult.nextElementSibling;
             }
-			switch(node.specification.type)
-			{
-			case "number":
-			case "question":
-				var child = this.parent.document.createElement('response');
-				child.textContent = node.response;
-				surveyresult.appendChild(child);
-				break;
-			case "radio":
-				var child = this.parent.document.createElement('response');
-				child.setAttribute('name',node.response.name);
-				child.textContent = node.response.text;
-				surveyresult.appendChild(child);
-				break;
-			case "checkbox":
-                if (node.response == undefined) {
-                    surveyresult.appendChild(this.parent.document.createElement('response'));
+            switch (node.specification.type) {
+                case "number":
+                case "question":
+                    var child = this.parent.document.createElement('response');
+                    child.textContent = node.response;
+                    surveyresult.appendChild(child);
                     break;
+                case "radio":
+                    var child = this.parent.document.createElement('response');
+                    child.setAttribute('name', node.response.name);
+                    child.textContent = node.response.text;
+                    surveyresult.appendChild(child);
+                    break;
+                case "checkbox":
+                    if (node.response == undefined) {
+                        surveyresult.appendChild(this.parent.document.createElement('response'));
+                        break;
+                    }
+                    for (var i = 0; i < node.response.length; i++) {
+                        var checkNode = this.parent.document.createElement('response');
+                        checkNode.setAttribute('name', node.response[i].name);
+                        checkNode.setAttribute('checked', node.response[i].checked);
+                        surveyresult.appendChild(checkNode);
+                    }
+                    break;
+            }
+        };
+        this.complete = function () {
+            this.state = "complete";
+            this.XMLDOM.setAttribute("state", this.state);
+        }
+    };
+
+    this.pageNode = function (parent, specification) {
+        // Create one store per test page
+        this.specification = specification;
+        this.parent = parent;
+        this.state = "empty";
+        this.XMLDOM = this.parent.document.createElement('page');
+        this.XMLDOM.setAttribute('ref', specification.id);
+        this.XMLDOM.setAttribute('presentedId', specification.presentedId);
+        this.XMLDOM.setAttribute("state", this.state);
+        if (specification.preTest != undefined) {
+            this.preTest = new this.parent.surveyNode(this.parent, this.XMLDOM, this.specification.preTest);
+        }
+        if (specification.postTest != undefined) {
+            this.postTest = new this.parent.surveyNode(this.parent, this.XMLDOM, this.specification.postTest);
+        }
+
+        // Add any page metrics
+        var page_metric = this.parent.document.createElement('metric');
+        this.XMLDOM.appendChild(page_metric);
+
+        // Add the audioelement
+        for (var element of this.specification.audioElements) {
+            var aeNode = this.parent.document.createElement('audioelement');
+            aeNode.setAttribute('ref', element.id);
+            if (element.name != undefined) {
+                aeNode.setAttribute('name', element.name)
+            };
+            aeNode.setAttribute('type', element.type);
+            aeNode.setAttribute('url', element.url);
+            aeNode.setAttribute('fqurl', qualifyURL(element.url));
+            aeNode.setAttribute('gain', element.gain);
+            if (element.type == 'anchor' || element.type == 'reference') {
+                if (element.marker > 0) {
+                    aeNode.setAttribute('marker', element.marker);
                 }
-				for (var i=0; i<node.response.length; i++)
-				{
-					var checkNode = this.parent.document.createElement('response');
-					checkNode.setAttribute('name',node.response[i].name);
-					checkNode.setAttribute('checked',node.response[i].checked);
-					surveyresult.appendChild(checkNode);
-				}
-				break;
-			}
-		};
-        this.complete = function() {
+            }
+            var ae_metric = this.parent.document.createElement('metric');
+            aeNode.appendChild(ae_metric);
+            this.XMLDOM.appendChild(aeNode);
+        }
+
+        this.parent.root.appendChild(this.XMLDOM);
+
+        this.complete = function () {
             this.state = "complete";
-            this.XMLDOM.setAttribute("state",this.state);
+            this.XMLDOM.setAttribute("state", "complete");
         }
-	};
-	
-	this.pageNode = function(parent,specification)
-	{
-		// Create one store per test page
-		this.specification = specification;
-		this.parent = parent;
-        this.state = "empty";
-		this.XMLDOM = this.parent.document.createElement('page');
-		this.XMLDOM.setAttribute('ref',specification.id);
-		this.XMLDOM.setAttribute('presentedId',specification.presentedId);
-        this.XMLDOM.setAttribute("state",this.state);
-		if (specification.preTest != undefined){this.preTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.preTest);}
-		if (specification.postTest != undefined){this.postTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.postTest);}
-		
-		// Add any page metrics
-		var page_metric = this.parent.document.createElement('metric');
-		this.XMLDOM.appendChild(page_metric);
-		
-		// Add the audioelement
-		for (var element of this.specification.audioElements)
-		{
-			var aeNode = this.parent.document.createElement('audioelement');
-			aeNode.setAttribute('ref',element.id);
-            if (element.name != undefined){aeNode.setAttribute('name',element.name)};
-			aeNode.setAttribute('type',element.type);
-			aeNode.setAttribute('url', element.url);
-            aeNode.setAttribute('fqurl',qualifyURL(element.url));
-			aeNode.setAttribute('gain', element.gain);
-			if (element.type == 'anchor' || element.type == 'reference')
-			{
-				if (element.marker > 0)
-				{
-					aeNode.setAttribute('marker',element.marker);
-				}
-			}
-			var ae_metric = this.parent.document.createElement('metric');
-			aeNode.appendChild(ae_metric); 
-			this.XMLDOM.appendChild(aeNode);
-		}
-		
-		this.parent.root.appendChild(this.XMLDOM);
-        
-        this.complete = function() {
-            this.state = "complete";
-            this.XMLDOM.setAttribute("state","complete");
-        }
-	};
-    this.update = function() {
+    };
+    this.update = function () {
         this.SessionKey.update();
     }
-	this.finish = function()
-	{
-		if (this.state == 0)
-		{
+    this.finish = function () {
+        if (this.state == 0) {
             this.update();
-		}
-		this.state = 1;
-        this.root.setAttribute("state","complete");
-		return this.root;
-	};
+        }
+        this.state = 1;
+        this.root.setAttribute("state", "complete");
+        return this.root;
+    };
 }
 
 var window_depedancy_callback;
-window_depedancy_callback = window.setInterval(function(){
+window_depedancy_callback = window.setInterval(function () {
     if (check_dependancies()) {
         window.clearInterval(window_depedancy_callback);
         onload();
     } else {
         document.getElementById("topLevelBody").innerHTML = "<h1>Loading Resources</h1>";
     }
-},100);
\ No newline at end of file
+}, 100);
--- a/js/specification.js	Wed Sep 21 10:20:57 2016 +0100
+++ b/js/specification.js	Wed Sep 21 13:21:06 2016 +0100
@@ -495,13 +495,13 @@
             
             // Get the title
             var title = xml.getElementsByTagName('title');
-            if (title.length != 0) {
+            if (title.length != 0 && title[0].parentElement == xml) {
                 this.title = title[0].textContent;
             }
 			
 			// Get the Comment Box Prefix
 			var CBP = xml.getElementsByTagName('commentboxprefix');
-			if (CBP.length != 0) {
+			if (CBP.length != 0 && CBP[0].parentElement == xml) {
 				this.commentBoxPrefix = CBP[0].textContent;
 			}
 			
--- a/tests/examples/project.xml	Wed Sep 21 10:20:57 2016 +0100
+++ b/tests/examples/project.xml	Wed Sep 21 13:21:06 2016 +0100
@@ -94,7 +94,7 @@
 		</survey>
 	</page>
 	<page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' label="letter">
-		<commentboxprefix>Comment on fragment</commentboxprefix>
+        <commentboxprefix>Comment on fragment</commentboxprefix>
 		<interface name="preference">
 			<title>Example Test Question</title>
 			<scales>