nickjillings@1682
|
1 /**
|
nickjillings@1682
|
2 * core.js
|
nickjillings@1682
|
3 *
|
nickjillings@1682
|
4 * Main script to run, calls all other core functions and manages loading/store to backend.
|
nickjillings@1682
|
5 * Also contains all global variables.
|
nickjillings@1682
|
6 */
|
nickjillings@1682
|
7
|
nickjillings@1682
|
8 /* create the web audio API context and store in audioContext*/
|
nickjillings@1643
|
9 var audioContext; // Hold the browser web audio API
|
nickjillings@1643
|
10 var projectXML; // Hold the parsed setup XML
|
nickjillings@1324
|
11 var schemaXSD; // Hold the parsed schema XSD
|
nickjillings@1581
|
12 var specification;
|
nickjillings@1582
|
13 var interfaceContext;
|
nickjillings@1324
|
14 var storage;
|
nickjillings@1622
|
15 var popup; // Hold the interfacePopup object
|
nickjillings@1634
|
16 var testState;
|
nickjillings@1655
|
17 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order
|
nickjillings@1643
|
18 var audioEngineContext; // The custome AudioEngine object
|
nickjillings@1643
|
19 var projectReturn; // Hold the URL for the return
|
nickjillings@2013
|
20
|
nickjillings@1318
|
21
|
nickjillings@1318
|
22 // Add a prototype to the bufferSourceNode to reference to the audioObject holding it
|
nickjillings@1318
|
23 AudioBufferSourceNode.prototype.owner = undefined;
|
nickjillings@2101
|
24 // Add a prototype to the bufferSourceNode to hold when the object was given a play command
|
nickjillings@2101
|
25 AudioBufferSourceNode.prototype.playbackStartTime = undefined;
|
nickjillings@1318
|
26 // Add a prototype to the bufferNode to hold the desired LINEAR gain
|
nickjillings@1320
|
27 AudioBuffer.prototype.playbackGain = undefined;
|
nickjillings@1318
|
28 // Add a prototype to the bufferNode to hold the computed LUFS loudness
|
nickjillings@1318
|
29 AudioBuffer.prototype.lufs = undefined;
|
nickjillings@1318
|
30
|
nickjillings@1348
|
31 // Firefox does not have an XMLDocument.prototype.getElementsByName
|
nickjillings@1348
|
32 // and there is no searchAll style command, this custom function will
|
nickjillings@1348
|
33 // search all children recusrively for the name. Used for XSD where all
|
nickjillings@1348
|
34 // element nodes must have a name and therefore can pull the schema node
|
nickjillings@1348
|
35 XMLDocument.prototype.getAllElementsByName = function(name)
|
nickjillings@1348
|
36 {
|
nickjillings@1348
|
37 name = String(name);
|
nickjillings@1348
|
38 var selected = this.documentElement.getAllElementsByName(name);
|
nickjillings@1348
|
39 return selected;
|
nickjillings@1348
|
40 }
|
nickjillings@1348
|
41
|
nickjillings@1348
|
42 Element.prototype.getAllElementsByName = function(name)
|
nickjillings@1348
|
43 {
|
nickjillings@1348
|
44 name = String(name);
|
nickjillings@1348
|
45 var selected = [];
|
nickjillings@1348
|
46 var node = this.firstElementChild;
|
nickjillings@1348
|
47 while(node != null)
|
nickjillings@1348
|
48 {
|
nickjillings@1348
|
49 if (node.getAttribute('name') == name)
|
nickjillings@1348
|
50 {
|
nickjillings@1348
|
51 selected.push(node);
|
nickjillings@1348
|
52 }
|
nickjillings@1348
|
53 if (node.childElementCount > 0)
|
nickjillings@1348
|
54 {
|
nickjillings@1348
|
55 selected = selected.concat(node.getAllElementsByName(name));
|
nickjillings@1348
|
56 }
|
nickjillings@1348
|
57 node = node.nextElementSibling;
|
nickjillings@1348
|
58 }
|
nickjillings@1348
|
59 return selected;
|
nickjillings@1348
|
60 }
|
nickjillings@1348
|
61
|
nickjillings@1348
|
62 XMLDocument.prototype.getAllElementsByTagName = function(name)
|
nickjillings@1348
|
63 {
|
nickjillings@1348
|
64 name = String(name);
|
nickjillings@1348
|
65 var selected = this.documentElement.getAllElementsByTagName(name);
|
nickjillings@1348
|
66 return selected;
|
nickjillings@1348
|
67 }
|
nickjillings@1348
|
68
|
nickjillings@1348
|
69 Element.prototype.getAllElementsByTagName = function(name)
|
nickjillings@1348
|
70 {
|
nickjillings@1348
|
71 name = String(name);
|
nickjillings@1348
|
72 var selected = [];
|
nickjillings@1348
|
73 var node = this.firstElementChild;
|
nickjillings@1348
|
74 while(node != null)
|
nickjillings@1348
|
75 {
|
nickjillings@1348
|
76 if (node.nodeName == name)
|
nickjillings@1348
|
77 {
|
nickjillings@1348
|
78 selected.push(node);
|
nickjillings@1348
|
79 }
|
nickjillings@1348
|
80 if (node.childElementCount > 0)
|
nickjillings@1348
|
81 {
|
nickjillings@1348
|
82 selected = selected.concat(node.getAllElementsByTagName(name));
|
nickjillings@1348
|
83 }
|
nickjillings@1348
|
84 node = node.nextElementSibling;
|
nickjillings@1348
|
85 }
|
nickjillings@1348
|
86 return selected;
|
nickjillings@1348
|
87 }
|
nickjillings@1348
|
88
|
nickjillings@1348
|
89 // Firefox does not have an XMLDocument.prototype.getElementsByName
|
nickjillings@1348
|
90 if (typeof XMLDocument.prototype.getElementsByName != "function") {
|
nickjillings@1348
|
91 XMLDocument.prototype.getElementsByName = function(name)
|
nickjillings@1348
|
92 {
|
nickjillings@1348
|
93 name = String(name);
|
nickjillings@1348
|
94 var node = this.documentElement.firstElementChild;
|
nickjillings@1348
|
95 var selected = [];
|
nickjillings@1348
|
96 while(node != null)
|
nickjillings@1348
|
97 {
|
nickjillings@1348
|
98 if (node.getAttribute('name') == name)
|
nickjillings@1348
|
99 {
|
nickjillings@1348
|
100 selected.push(node);
|
nickjillings@1348
|
101 }
|
nickjillings@1348
|
102 node = node.nextElementSibling;
|
nickjillings@1348
|
103 }
|
nickjillings@1348
|
104 return selected;
|
nickjillings@1348
|
105 }
|
nickjillings@1348
|
106 }
|
nickjillings@1348
|
107
|
nickjillings@1682
|
108 window.onload = function() {
|
nickjillings@1682
|
109 // Function called once the browser has loaded all files.
|
nickjillings@1682
|
110 // This should perform any initial commands such as structure / loading documents
|
nickjillings@1682
|
111
|
nickjillings@1682
|
112 // Create a web audio API context
|
nickjillings@1701
|
113 // Fixed for cross-browser support
|
nickjillings@1701
|
114 var AudioContext = window.AudioContext || window.webkitAudioContext;
|
nickjillings@1688
|
115 audioContext = new AudioContext;
|
nickjillings@1682
|
116
|
nickjillings@1634
|
117 // Create test state
|
nickjillings@1634
|
118 testState = new stateMachine();
|
nickjillings@1634
|
119
|
nickjillings@1622
|
120 // Create the popup interface object
|
nickjillings@1622
|
121 popup = new interfacePopup();
|
nickjillings@1370
|
122
|
nickjillings@1370
|
123 // Create the specification object
|
nickjillings@1581
|
124 specification = new Specification();
|
nickjillings@1582
|
125
|
nickjillings@1582
|
126 // Create the interface object
|
nickjillings@1582
|
127 interfaceContext = new Interface(specification);
|
nickjillings@1324
|
128
|
nickjillings@1324
|
129 // Create the storage object
|
nickjillings@1324
|
130 storage = new Storage();
|
nickjillings@1410
|
131 // Define window callbacks for interface
|
nickjillings@1410
|
132 window.onresize = function(event){interfaceContext.resizeWindow(event);};
|
nickjillings@1697
|
133 };
|
nickjillings@1682
|
134
|
nickjillings@1408
|
135 function loadProjectSpec(url) {
|
nickjillings@1408
|
136 // Load the project document from the given URL, decode the XML and instruct audioEngine to get audio data
|
nickjillings@1408
|
137 // If url is null, request client to upload project XML document
|
nickjillings@1324
|
138 var xmlhttp = new XMLHttpRequest();
|
nickjillings@1324
|
139 xmlhttp.open("GET",'test-schema.xsd',true);
|
nickjillings@1324
|
140 xmlhttp.onload = function()
|
nickjillings@1324
|
141 {
|
nickjillings@1324
|
142 schemaXSD = xmlhttp.response;
|
nickjillings@1324
|
143 var parse = new DOMParser();
|
nickjillings@1324
|
144 specification.schema = parse.parseFromString(xmlhttp.response,'text/xml');
|
nickjillings@1324
|
145 var r = new XMLHttpRequest();
|
nickjillings@1324
|
146 r.open('GET',url,true);
|
nickjillings@1324
|
147 r.onload = function() {
|
nickjillings@1324
|
148 loadProjectSpecCallback(r.response);
|
nickjillings@1324
|
149 };
|
nickjillings@2110
|
150 r.onerror = function() {
|
nickjillings@2110
|
151 document.getElementsByTagName('body')[0].innerHTML = null;
|
nickjillings@2110
|
152 var msg = document.createElement("h3");
|
nickjillings@2110
|
153 msg.textContent = "FATAL ERROR";
|
nickjillings@2110
|
154 var span = document.createElement("p");
|
nickjillings@2110
|
155 span.textContent = "There was an error when loading your XML file. Please check your path in the URL. After the path to this page, there should be '?url=path/to/your/file.xml'. Check the spelling of your filename as well. If you are still having issues, check the log of the python server or your webserver distribution for 404 codes for your file.";
|
nickjillings@2110
|
156 document.getElementsByTagName('body')[0].appendChild(msg);
|
nickjillings@2110
|
157 document.getElementsByTagName('body')[0].appendChild(span);
|
nickjillings@2110
|
158 }
|
nickjillings@1324
|
159 r.send();
|
nickjillings@1408
|
160 };
|
nickjillings@1324
|
161 xmlhttp.send();
|
nickjillings@1408
|
162 };
|
nickjillings@1408
|
163
|
nickjillings@1408
|
164 function loadProjectSpecCallback(response) {
|
nickjillings@1408
|
165 // Function called after asynchronous download of XML project specification
|
nickjillings@1408
|
166 //var decode = $.parseXML(response);
|
nickjillings@1408
|
167 //projectXML = $(decode);
|
nickjillings@1408
|
168
|
nickjillings@2147
|
169 // Check if XML is new or a resumption
|
nickjillings@2147
|
170 var parse = new DOMParser();
|
nickjillings@2147
|
171 var responseDocument = parse.parseFromString(response,'text/xml');
|
nickjillings@2147
|
172 var errorNode = responseDocument.getElementsByTagName('parsererror');
|
nickjillings@1443
|
173 if (errorNode.length >= 1)
|
nickjillings@1443
|
174 {
|
nickjillings@1443
|
175 var msg = document.createElement("h3");
|
nickjillings@1443
|
176 msg.textContent = "FATAL ERROR";
|
nickjillings@1443
|
177 var span = document.createElement("span");
|
nickjillings@1443
|
178 span.textContent = "The XML parser returned the following errors when decoding your XML file";
|
nickjillings@1445
|
179 document.getElementsByTagName('body')[0].innerHTML = null;
|
nickjillings@1443
|
180 document.getElementsByTagName('body')[0].appendChild(msg);
|
nickjillings@1443
|
181 document.getElementsByTagName('body')[0].appendChild(span);
|
nickjillings@1443
|
182 document.getElementsByTagName('body')[0].appendChild(errorNode[0]);
|
nickjillings@1443
|
183 return;
|
nickjillings@1443
|
184 }
|
nickjillings@2169
|
185 if (responseDocument == undefined) {
|
nickjillings@2169
|
186 var msg = document.createElement("h3");
|
nickjillings@2169
|
187 msg.textContent = "FATAL ERROR";
|
nickjillings@2169
|
188 var span = document.createElement("span");
|
nickjillings@2169
|
189 span.textContent = "The project XML was not decoded properly, try refreshing your browser and clearing caches. If the problem persists, contact the test creator.";
|
nickjillings@2169
|
190 document.getElementsByTagName('body')[0].innerHTML = null;
|
nickjillings@2169
|
191 document.getElementsByTagName('body')[0].appendChild(msg);
|
nickjillings@2169
|
192 document.getElementsByTagName('body')[0].appendChild(span);
|
nickjillings@2169
|
193 return;
|
nickjillings@2169
|
194 }
|
nickjillings@2147
|
195 if (responseDocument.children[0].nodeName == "waet") {
|
nickjillings@2147
|
196 // document is a specification
|
nickjillings@2147
|
197
|
nickjillings@2147
|
198 // Perform XML schema validation
|
nickjillings@2147
|
199 var Module = {
|
nickjillings@2147
|
200 xml: response,
|
nickjillings@2147
|
201 schema: schemaXSD,
|
nickjillings@2147
|
202 arguments:["--noout", "--schema", 'test-schema.xsd','document.xml']
|
nickjillings@2147
|
203 };
|
nickjillings@2147
|
204 projectXML = responseDocument;
|
nickjillings@2147
|
205 var xmllint = validateXML(Module);
|
nickjillings@2147
|
206 console.log(xmllint);
|
nickjillings@2147
|
207 if(xmllint != 'document.xml validates\n')
|
nickjillings@2147
|
208 {
|
nickjillings@2147
|
209 document.getElementsByTagName('body')[0].innerHTML = null;
|
nickjillings@2147
|
210 var msg = document.createElement("h3");
|
nickjillings@2147
|
211 msg.textContent = "FATAL ERROR";
|
nickjillings@2147
|
212 var span = document.createElement("h4");
|
nickjillings@2147
|
213 span.textContent = "The XML validator returned the following errors when decoding your XML file";
|
nickjillings@2147
|
214 document.getElementsByTagName('body')[0].appendChild(msg);
|
nickjillings@2147
|
215 document.getElementsByTagName('body')[0].appendChild(span);
|
nickjillings@2147
|
216 xmllint = xmllint.split('\n');
|
nickjillings@2147
|
217 for (var i in xmllint)
|
nickjillings@2147
|
218 {
|
nickjillings@2147
|
219 document.getElementsByTagName('body')[0].appendChild(document.createElement('br'));
|
nickjillings@2147
|
220 var span = document.createElement("span");
|
nickjillings@2147
|
221 span.textContent = xmllint[i];
|
nickjillings@2147
|
222 document.getElementsByTagName('body')[0].appendChild(span);
|
nickjillings@2147
|
223 }
|
nickjillings@2147
|
224 return;
|
nickjillings@2147
|
225 }
|
nickjillings@2149
|
226 // Build the specification
|
nickjillings@2149
|
227 specification.decode(projectXML);
|
nickjillings@2147
|
228 // Generate the session-key
|
nickjillings@2147
|
229 storage.initialise();
|
nickjillings@2147
|
230
|
nickjillings@2147
|
231 } else if (responseDocument.children[0].nodeName == "waetresult") {
|
nickjillings@2147
|
232 // document is a result
|
nickjillings@1294
|
233 projectXML = document.implementation.createDocument(null,"waet");
|
nickjillings@1294
|
234 projectXML.children[0].appendChild(responseDocument.getElementsByTagName('waet')[0].getElementsByTagName("setup")[0].cloneNode(true));
|
nickjillings@1294
|
235 var child = responseDocument.children[0].children[0];
|
nickjillings@1294
|
236 while (child != null) {
|
nickjillings@1294
|
237 if (child.nodeName == "survey") {
|
nickjillings@1294
|
238 // One of the global survey elements
|
nickjillings@1294
|
239 if (child.getAttribute("state") == "complete") {
|
nickjillings@1294
|
240 // We need to remove this survey from <setup>
|
nickjillings@1294
|
241 var location = child.getAttribute("location");
|
nickjillings@1294
|
242 var globalSurveys = projectXML.getElementsByTagName("setup")[0].getElementsByTagName("survey")[0];
|
nickjillings@1294
|
243 while(globalSurveys != null) {
|
nickjillings@1294
|
244 if (location == "pre" || location == "before") {
|
nickjillings@1294
|
245 if (globalSurveys.getAttribute("location") == "pre" || globalSurveys.getAttribute("location") == "before") {
|
nickjillings@1294
|
246 projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys);
|
nickjillings@1294
|
247 break;
|
nickjillings@1294
|
248 }
|
nickjillings@1294
|
249 } else {
|
nickjillings@1294
|
250 if (globalSurveys.getAttribute("location") == "post" || globalSurveys.getAttribute("location") == "after") {
|
nickjillings@1294
|
251 projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys);
|
nickjillings@1294
|
252 break;
|
nickjillings@1294
|
253 }
|
nickjillings@1294
|
254 }
|
nickjillings@1294
|
255 globalSurveys = globalSurveys.nextElementSibling;
|
nickjillings@1294
|
256 }
|
nickjillings@1294
|
257 } else {
|
nickjillings@1294
|
258 // We need to complete this, so it must be regenerated by store
|
nickjillings@1294
|
259 var copy = child;
|
nickjillings@1294
|
260 child = child.previousElementSibling;
|
nickjillings@1294
|
261 responseDocument.children[0].removeChild(copy);
|
nickjillings@1294
|
262 }
|
nickjillings@1294
|
263 } else if (child.nodeName == "page") {
|
nickjillings@1294
|
264 if (child.getAttribute("state") == "empty") {
|
nickjillings@1294
|
265 // We need to complete this page
|
nickjillings@1294
|
266 projectXML.children[0].appendChild(responseDocument.getElementById(child.getAttribute("ref")).cloneNode(true));
|
nickjillings@1294
|
267 var copy = child;
|
nickjillings@1294
|
268 child = child.previousElementSibling;
|
nickjillings@1294
|
269 responseDocument.children[0].removeChild(copy);
|
nickjillings@1294
|
270 }
|
nickjillings@1294
|
271 }
|
nickjillings@1294
|
272 child = child.nextElementSibling;
|
nickjillings@1294
|
273 }
|
nickjillings@2149
|
274 // Build the specification
|
nickjillings@2149
|
275 specification.decode(projectXML);
|
nickjillings@1294
|
276 // Use the original
|
nickjillings@1294
|
277 storage.initialise(responseDocument);
|
nickjillings@2147
|
278 }
|
nickjillings@1339
|
279 /// CHECK FOR SAMPLE RATE COMPATIBILITY
|
nickjillings@1339
|
280 if (specification.sampleRate != undefined) {
|
nickjillings@1339
|
281 if (Number(specification.sampleRate) != audioContext.sampleRate) {
|
nickjillings@1339
|
282 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.';
|
nickjillings@1339
|
283 alert(errStr);
|
nickjillings@1339
|
284 return;
|
nickjillings@1339
|
285 }
|
nickjillings@1339
|
286 }
|
nickjillings@1408
|
287
|
nickjillings@1408
|
288 // Detect the interface to use and load the relevant javascripts.
|
nickjillings@1408
|
289 var interfaceJS = document.createElement('script');
|
nickjillings@1408
|
290 interfaceJS.setAttribute("type","text/javascript");
|
nickjillings@1329
|
291 switch(specification.interface)
|
nickjillings@1329
|
292 {
|
nickjillings@1329
|
293 case "APE":
|
nickjillings@2161
|
294 interfaceJS.setAttribute("src","interfaces/ape.js");
|
nickjillings@2161
|
295
|
nickjillings@2161
|
296 // APE comes with a css file
|
nickjillings@2161
|
297 var css = document.createElement('link');
|
nickjillings@2161
|
298 css.rel = 'stylesheet';
|
nickjillings@2161
|
299 css.type = 'text/css';
|
nickjillings@2161
|
300 css.href = 'interfaces/ape.css';
|
nickjillings@2161
|
301
|
nickjillings@2161
|
302 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
303 break;
|
nickjillings@2161
|
304
|
nickjillings@1329
|
305 case "MUSHRA":
|
nickjillings@2161
|
306 interfaceJS.setAttribute("src","interfaces/mushra.js");
|
nickjillings@2161
|
307
|
nickjillings@2161
|
308 // MUSHRA comes with a css file
|
nickjillings@2161
|
309 var css = document.createElement('link');
|
nickjillings@2161
|
310 css.rel = 'stylesheet';
|
nickjillings@2161
|
311 css.type = 'text/css';
|
nickjillings@2161
|
312 css.href = 'interfaces/mushra.css';
|
nickjillings@2161
|
313
|
nickjillings@2161
|
314 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
315 break;
|
nickjillings@1329
|
316
|
nickjillings@1329
|
317 case "AB":
|
nickjillings@2161
|
318 interfaceJS.setAttribute("src","interfaces/AB.js");
|
nickjillings@2161
|
319
|
nickjillings@2161
|
320 // AB comes with a css file
|
nickjillings@2161
|
321 var css = document.createElement('link');
|
nickjillings@2161
|
322 css.rel = 'stylesheet';
|
nickjillings@2161
|
323 css.type = 'text/css';
|
nickjillings@2161
|
324 css.href = 'interfaces/AB.css';
|
nickjillings@2161
|
325
|
nickjillings@2161
|
326 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
327 break;
|
nickjillings@2161
|
328
|
nickjillings@2161
|
329 case "ABX":
|
nickjillings@2161
|
330 interfaceJS.setAttribute("src","interfaces/ABX.js");
|
nickjillings@2161
|
331
|
nickjillings@2161
|
332 // AB comes with a css file
|
nickjillings@2161
|
333 var css = document.createElement('link');
|
nickjillings@2161
|
334 css.rel = 'stylesheet';
|
nickjillings@2161
|
335 css.type = 'text/css';
|
nickjillings@2161
|
336 css.href = 'interfaces/ABX.css';
|
nickjillings@2161
|
337
|
nickjillings@2161
|
338 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
339 break;
|
nickjillings@2161
|
340
|
nickjillings@1345
|
341 case "Bipolar":
|
nickjillings@1345
|
342 case "ACR":
|
nickjillings@1345
|
343 case "DCR":
|
nickjillings@1345
|
344 case "CCR":
|
nickjillings@1343
|
345 case "ABC":
|
nickjillings@2161
|
346 // Above enumerate to horizontal sliders
|
nickjillings@2161
|
347 interfaceJS.setAttribute("src","interfaces/horizontal-sliders.js");
|
nickjillings@2161
|
348
|
nickjillings@2161
|
349 // horizontal-sliders comes with a css file
|
nickjillings@2161
|
350 var css = document.createElement('link');
|
nickjillings@2161
|
351 css.rel = 'stylesheet';
|
nickjillings@2161
|
352 css.type = 'text/css';
|
nickjillings@2161
|
353 css.href = 'interfaces/horizontal-sliders.css';
|
nickjillings@2161
|
354
|
nickjillings@2161
|
355 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
356 break;
|
nickjillings@1345
|
357 case "discrete":
|
nickjillings@1345
|
358 case "likert":
|
nickjillings@2161
|
359 // Above enumerate to horizontal discrete radios
|
nickjillings@2161
|
360 interfaceJS.setAttribute("src","interfaces/discrete.js");
|
nickjillings@2161
|
361
|
nickjillings@2161
|
362 // horizontal-sliders comes with a css file
|
nickjillings@2161
|
363 var css = document.createElement('link');
|
nickjillings@2161
|
364 css.rel = 'stylesheet';
|
nickjillings@2161
|
365 css.type = 'text/css';
|
nickjillings@2161
|
366 css.href = 'interfaces/discrete.css';
|
nickjillings@2161
|
367
|
nickjillings@2161
|
368 document.getElementsByTagName("head")[0].appendChild(css);
|
nickjillings@2161
|
369 break;
|
nickjillings@1408
|
370 }
|
nickjillings@1408
|
371 document.getElementsByTagName("head")[0].appendChild(interfaceJS);
|
nickjillings@1408
|
372
|
nickjillings@1410
|
373 // Create the audio engine object
|
nickjillings@1410
|
374 audioEngineContext = new AudioEngine(specification);
|
nickjillings@1408
|
375 }
|
nickjillings@1408
|
376
|
nickjillings@1408
|
377 function createProjectSave(destURL) {
|
nickjillings@2167
|
378 // Clear the window.onbeforeunload
|
nickjillings@2167
|
379 window.onbeforeunload = null;
|
nickjillings@1408
|
380 // Save the data from interface into XML and send to destURL
|
nickjillings@1408
|
381 // If destURL is null then download XML in client
|
nickjillings@1408
|
382 // Now time to render file locally
|
nickjillings@1408
|
383 var xmlDoc = interfaceXMLSave();
|
nickjillings@1408
|
384 var parent = document.createElement("div");
|
nickjillings@1408
|
385 parent.appendChild(xmlDoc);
|
nickjillings@1408
|
386 var file = [parent.innerHTML];
|
nickjillings@2150
|
387 if (destURL == "local") {
|
nickjillings@1408
|
388 var bb = new Blob(file,{type : 'application/xml'});
|
nickjillings@1408
|
389 var dnlk = window.URL.createObjectURL(bb);
|
nickjillings@1408
|
390 var a = document.createElement("a");
|
nickjillings@1408
|
391 a.hidden = '';
|
nickjillings@1408
|
392 a.href = dnlk;
|
nickjillings@1408
|
393 a.download = "save.xml";
|
nickjillings@1408
|
394 a.textContent = "Save File";
|
nickjillings@1408
|
395
|
nickjillings@1408
|
396 popup.showPopup();
|
nickjillings@1332
|
397 popup.popupContent.innerHTML = "</span>Please save the file below to give to your test supervisor</span><br>";
|
nickjillings@1408
|
398 popup.popupContent.appendChild(a);
|
nickjillings@1408
|
399 } else {
|
nickjillings@1408
|
400 var xmlhttp = new XMLHttpRequest;
|
nickjillings@1293
|
401 xmlhttp.open("POST","\save.php?key="+storage.SessionKey.key,true);
|
nickjillings@1408
|
402 xmlhttp.setRequestHeader('Content-Type', 'text/xml');
|
nickjillings@1408
|
403 xmlhttp.onerror = function(){
|
nickjillings@1408
|
404 console.log('Error saving file to server! Presenting download locally');
|
nickjillings@1293
|
405 createProjectSave("local");
|
nickjillings@1408
|
406 };
|
nickjillings@2150
|
407 xmlhttp.onload = function() {
|
nickjillings@2150
|
408 console.log(xmlhttp);
|
nickjillings@2150
|
409 if (this.status >= 300) {
|
nickjillings@2150
|
410 console.log("WARNING - Could not update at this time");
|
nickjillings@1293
|
411 createProjectSave("local");
|
nickjillings@2150
|
412 } else {
|
nickjillings@2150
|
413 var parser = new DOMParser();
|
nickjillings@2150
|
414 var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml");
|
nickjillings@2150
|
415 var response = xmlDoc.getElementsByTagName('response')[0];
|
nickjillings@2150
|
416 if (response.getAttribute("state") == "OK") {
|
nickjillings@2150
|
417 var file = response.getElementsByTagName("file")[0];
|
nickjillings@2150
|
418 console.log("Save: OK, written "+file.getAttribute("bytes")+"B");
|
nickjillings@2155
|
419 popup.popupContent.textContent = "Thank you. Your session has been saved.";
|
nickjillings@2150
|
420 } else {
|
nickjillings@2150
|
421 var message = response.getElementsByTagName("message");
|
nickjillings@2150
|
422 console.log("Save: Error! "+message.textContent);
|
nickjillings@2150
|
423 createProjectSave("local");
|
nickjillings@2150
|
424 }
|
nickjillings@2150
|
425 }
|
nickjillings@2150
|
426 };
|
nickjillings@1408
|
427 xmlhttp.send(file);
|
nickjillings@1332
|
428 popup.showPopup();
|
nickjillings@1332
|
429 popup.popupContent.innerHTML = null;
|
nickjillings@1332
|
430 popup.popupContent.textContent = "Submitting. Please Wait";
|
nickjillings@2106
|
431 popup.hideNextButton();
|
nickjillings@2106
|
432 popup.hidePreviousButton();
|
nickjillings@1408
|
433 }
|
nickjillings@1408
|
434 }
|
nickjillings@1408
|
435
|
nickjillings@1408
|
436 function errorSessionDump(msg){
|
nickjillings@1408
|
437 // Create the partial interface XML save
|
nickjillings@1408
|
438 // Include error node with message on why the dump occured
|
nickjillings@1443
|
439 popup.showPopup();
|
nickjillings@1443
|
440 popup.popupContent.innerHTML = null;
|
nickjillings@1443
|
441 var err = document.createElement('error');
|
nickjillings@1443
|
442 var parent = document.createElement("div");
|
nickjillings@1443
|
443 if (typeof msg === "object")
|
nickjillings@1443
|
444 {
|
nickjillings@1443
|
445 err.appendChild(msg);
|
nickjillings@1443
|
446 popup.popupContent.appendChild(msg);
|
nickjillings@1443
|
447
|
nickjillings@1443
|
448 } else {
|
nickjillings@1443
|
449 err.textContent = msg;
|
nickjillings@1443
|
450 popup.popupContent.innerHTML = "ERROR : "+msg;
|
nickjillings@1443
|
451 }
|
nickjillings@1408
|
452 var xmlDoc = interfaceXMLSave();
|
nickjillings@1408
|
453 xmlDoc.appendChild(err);
|
nickjillings@1408
|
454 parent.appendChild(xmlDoc);
|
nickjillings@1408
|
455 var file = [parent.innerHTML];
|
nickjillings@1408
|
456 var bb = new Blob(file,{type : 'application/xml'});
|
nickjillings@1408
|
457 var dnlk = window.URL.createObjectURL(bb);
|
nickjillings@1408
|
458 var a = document.createElement("a");
|
nickjillings@1408
|
459 a.hidden = '';
|
nickjillings@1408
|
460 a.href = dnlk;
|
nickjillings@1408
|
461 a.download = "save.xml";
|
nickjillings@1408
|
462 a.textContent = "Save File";
|
nickjillings@1408
|
463
|
nickjillings@1443
|
464
|
nickjillings@1443
|
465
|
nickjillings@1408
|
466 popup.popupContent.appendChild(a);
|
nickjillings@1408
|
467 }
|
nickjillings@1408
|
468
|
nickjillings@1408
|
469 // Only other global function which must be defined in the interface class. Determines how to create the XML document.
|
nickjillings@1408
|
470 function interfaceXMLSave(){
|
nickjillings@1408
|
471 // Create the XML string to be exported with results
|
nickjillings@1324
|
472 return storage.finish();
|
nickjillings@1408
|
473 }
|
nickjillings@1408
|
474
|
nickjillings@1426
|
475 function linearToDecibel(gain)
|
nickjillings@1426
|
476 {
|
nickjillings@1426
|
477 return 20.0*Math.log10(gain);
|
nickjillings@1426
|
478 }
|
nickjillings@1426
|
479
|
nickjillings@1426
|
480 function decibelToLinear(gain)
|
nickjillings@1426
|
481 {
|
nickjillings@1426
|
482 return Math.pow(10,gain/20.0);
|
nickjillings@1426
|
483 }
|
nickjillings@1426
|
484
|
nickjillings@2147
|
485 function randomString(length) {
|
nickjillings@2147
|
486 return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
|
nickjillings@2147
|
487 }
|
nickjillings@2147
|
488
|
nickjillings@1622
|
489 function interfacePopup() {
|
nickjillings@1622
|
490 // Creates an object to manage the popup
|
nickjillings@1622
|
491 this.popup = null;
|
nickjillings@1622
|
492 this.popupContent = null;
|
nickjillings@1526
|
493 this.popupTitle = null;
|
nickjillings@1526
|
494 this.popupResponse = null;
|
nickjillings@1574
|
495 this.buttonProceed = null;
|
nickjillings@2034
|
496 this.buttonPrevious = null;
|
nickjillings@1622
|
497 this.popupOptions = null;
|
nickjillings@1622
|
498 this.currentIndex = null;
|
nickjillings@1324
|
499 this.node = null;
|
nickjillings@1324
|
500 this.store = null;
|
nickjillings@1422
|
501 $(window).keypress(function(e){
|
nickjillings@1422
|
502 if (e.keyCode == 13 && popup.popup.style.visibility == 'visible')
|
nickjillings@1422
|
503 {
|
nickjillings@1422
|
504 console.log(e);
|
nickjillings@1422
|
505 popup.buttonProceed.onclick();
|
nickjillings@1424
|
506 e.preventDefault();
|
nickjillings@1422
|
507 }
|
nickjillings@1422
|
508 });
|
nickjillings@1581
|
509
|
nickjillings@1622
|
510 this.createPopup = function(){
|
nickjillings@1622
|
511 // Create popup window interface
|
nickjillings@1622
|
512 var insertPoint = document.getElementById("topLevelBody");
|
nickjillings@1622
|
513
|
nickjillings@1379
|
514 this.popup = document.getElementById('popupHolder');
|
nickjillings@1622
|
515 this.popup.style.left = (window.innerWidth/2)-250 + 'px';
|
nickjillings@1622
|
516 this.popup.style.top = (window.innerHeight/2)-125 + 'px';
|
nickjillings@1622
|
517
|
nickjillings@1379
|
518 this.popupContent = document.getElementById('popupContent');
|
nickjillings@1622
|
519
|
nickjillings@1379
|
520 this.popupTitle = document.getElementById('popupTitle');
|
nickjillings@1526
|
521
|
nickjillings@1379
|
522 this.popupResponse = document.getElementById('popupResponse');
|
nickjillings@1526
|
523
|
nickjillings@1379
|
524 this.buttonProceed = document.getElementById('popup-proceed');
|
nickjillings@1574
|
525 this.buttonProceed.onclick = function(){popup.proceedClicked();};
|
nickjillings@2034
|
526
|
nickjillings@1379
|
527 this.buttonPrevious = document.getElementById('popup-previous');
|
nickjillings@2034
|
528 this.buttonPrevious.onclick = function(){popup.previousClick();};
|
nickjillings@2034
|
529
|
nickjillings@1379
|
530 this.hidePopup();
|
nickjillings@1379
|
531
|
nickjillings@1581
|
532 this.popup.style.zIndex = -1;
|
nickjillings@1581
|
533 this.popup.style.visibility = 'hidden';
|
nickjillings@1622
|
534 };
|
nickjillings@1621
|
535
|
nickjillings@1622
|
536 this.showPopup = function(){
|
nickjillings@1581
|
537 if (this.popup == null) {
|
nickjillings@1622
|
538 this.createPopup();
|
nickjillings@1622
|
539 }
|
nickjillings@1622
|
540 this.popup.style.zIndex = 3;
|
nickjillings@1622
|
541 this.popup.style.visibility = 'visible';
|
nickjillings@1622
|
542 var blank = document.getElementsByClassName('testHalt')[0];
|
nickjillings@1622
|
543 blank.style.zIndex = 2;
|
nickjillings@1622
|
544 blank.style.visibility = 'visible';
|
nickjillings@1622
|
545 };
|
nickjillings@1622
|
546
|
nickjillings@1622
|
547 this.hidePopup = function(){
|
nickjillings@1622
|
548 this.popup.style.zIndex = -1;
|
nickjillings@1622
|
549 this.popup.style.visibility = 'hidden';
|
nickjillings@1622
|
550 var blank = document.getElementsByClassName('testHalt')[0];
|
nickjillings@1622
|
551 blank.style.zIndex = -2;
|
nickjillings@1622
|
552 blank.style.visibility = 'hidden';
|
nickjillings@1526
|
553 this.buttonPrevious.style.visibility = 'inherit';
|
nickjillings@1622
|
554 };
|
nickjillings@1622
|
555
|
nickjillings@1622
|
556 this.postNode = function() {
|
nickjillings@1622
|
557 // This will take the node from the popupOptions and display it
|
nickjillings@1622
|
558 var node = this.popupOptions[this.currentIndex];
|
nickjillings@1526
|
559 this.popupResponse.innerHTML = null;
|
nickjillings@1324
|
560 this.popupTitle.textContent = node.specification.statement;
|
nickjillings@1324
|
561 if (node.specification.type == 'question') {
|
nickjillings@1622
|
562 var textArea = document.createElement('textarea');
|
nickjillings@1324
|
563 switch (node.specification.boxsize) {
|
nickjillings@2030
|
564 case 'small':
|
nickjillings@2030
|
565 textArea.cols = "20";
|
nickjillings@2030
|
566 textArea.rows = "1";
|
nickjillings@2030
|
567 break;
|
nickjillings@2030
|
568 case 'normal':
|
nickjillings@2030
|
569 textArea.cols = "30";
|
nickjillings@2030
|
570 textArea.rows = "2";
|
nickjillings@2030
|
571 break;
|
nickjillings@2030
|
572 case 'large':
|
nickjillings@2030
|
573 textArea.cols = "40";
|
nickjillings@2030
|
574 textArea.rows = "5";
|
nickjillings@2030
|
575 break;
|
nickjillings@2030
|
576 case 'huge':
|
nickjillings@2030
|
577 textArea.cols = "50";
|
nickjillings@2030
|
578 textArea.rows = "10";
|
nickjillings@2030
|
579 break;
|
nickjillings@2030
|
580 }
|
nickjillings@1361
|
581 if (node.response == undefined) {
|
nickjillings@1361
|
582 node.response = "";
|
nickjillings@1361
|
583 } else {
|
nickjillings@1361
|
584 textArea.value = node.response;
|
nickjillings@1361
|
585 }
|
nickjillings@1526
|
586 this.popupResponse.appendChild(textArea);
|
nickjillings@1526
|
587 textArea.focus();
|
nickjillings@1382
|
588 this.popupResponse.style.textAlign="center";
|
nickjillings@1382
|
589 this.popupResponse.style.left="0%";
|
nickjillings@1324
|
590 } else if (node.specification.type == 'checkbox') {
|
nickjillings@1361
|
591 if (node.response == undefined) {
|
nickjillings@1361
|
592 node.response = Array(node.specification.options.length);
|
nickjillings@1361
|
593 }
|
nickjillings@1361
|
594 var index = 0;
|
nickjillings@1382
|
595 var max_w = 0;
|
nickjillings@1324
|
596 for (var option of node.specification.options) {
|
nickjillings@1588
|
597 var input = document.createElement('input');
|
nickjillings@2093
|
598 input.id = option.name;
|
nickjillings@1588
|
599 input.type = 'checkbox';
|
nickjillings@1588
|
600 var span = document.createElement('span');
|
nickjillings@1588
|
601 span.textContent = option.text;
|
nickjillings@1588
|
602 var hold = document.createElement('div');
|
nickjillings@1588
|
603 hold.setAttribute('name','option');
|
nickjillings@1588
|
604 hold.style.padding = '4px';
|
nickjillings@1588
|
605 hold.appendChild(input);
|
nickjillings@1588
|
606 hold.appendChild(span);
|
nickjillings@1324
|
607 this.popupResponse.appendChild(hold);
|
nickjillings@1361
|
608 if (node.response[index] != undefined){
|
nickjillings@1361
|
609 if (node.response[index].checked == true) {
|
nickjillings@1361
|
610 input.checked = "true";
|
nickjillings@1361
|
611 }
|
nickjillings@1361
|
612 }
|
nickjillings@1382
|
613 var w = $(span).width();
|
nickjillings@1382
|
614 if (w > max_w)
|
nickjillings@1382
|
615 max_w = w;
|
nickjillings@1361
|
616 index++;
|
nickjillings@1588
|
617 }
|
nickjillings@1382
|
618 max_w += 12;
|
nickjillings@1382
|
619 this.popupResponse.style.textAlign="";
|
nickjillings@1382
|
620 var leftP = ((max_w/500)/2)*100;
|
nickjillings@1382
|
621 this.popupResponse.style.left=leftP+"%";
|
nickjillings@1324
|
622 } else if (node.specification.type == 'radio') {
|
nickjillings@1361
|
623 if (node.response == undefined) {
|
nickjillings@1361
|
624 node.response = {name: "", text: ""};
|
nickjillings@1361
|
625 }
|
nickjillings@1361
|
626 var index = 0;
|
nickjillings@1382
|
627 var max_w = 0;
|
nickjillings@1324
|
628 for (var option of node.specification.options) {
|
nickjillings@1589
|
629 var input = document.createElement('input');
|
nickjillings@1589
|
630 input.id = option.name;
|
nickjillings@1589
|
631 input.type = 'radio';
|
nickjillings@1324
|
632 input.name = node.specification.id;
|
nickjillings@1589
|
633 var span = document.createElement('span');
|
nickjillings@1589
|
634 span.textContent = option.text;
|
nickjillings@1589
|
635 var hold = document.createElement('div');
|
nickjillings@1589
|
636 hold.setAttribute('name','option');
|
nickjillings@1589
|
637 hold.style.padding = '4px';
|
nickjillings@1589
|
638 hold.appendChild(input);
|
nickjillings@1589
|
639 hold.appendChild(span);
|
nickjillings@1324
|
640 this.popupResponse.appendChild(hold);
|
nickjillings@1361
|
641 if (input.id == node.response.name) {
|
nickjillings@1361
|
642 input.checked = "true";
|
nickjillings@1361
|
643 }
|
nickjillings@1382
|
644 var w = $(span).width();
|
nickjillings@1382
|
645 if (w > max_w)
|
nickjillings@1382
|
646 max_w = w;
|
nickjillings@1589
|
647 }
|
nickjillings@1382
|
648 max_w += 12;
|
nickjillings@1382
|
649 this.popupResponse.style.textAlign="";
|
nickjillings@1382
|
650 var leftP = ((max_w/500)/2)*100;
|
nickjillings@1382
|
651 this.popupResponse.style.left=leftP+"%";
|
nickjillings@1324
|
652 } else if (node.specification.type == 'number') {
|
nickjillings@1573
|
653 var input = document.createElement('input');
|
nickjillings@2044
|
654 input.type = 'textarea';
|
nickjillings@1324
|
655 if (node.min != null) {input.min = node.specification.min;}
|
nickjillings@1324
|
656 if (node.max != null) {input.max = node.specification.max;}
|
nickjillings@1324
|
657 if (node.step != null) {input.step = node.specification.step;}
|
nickjillings@1361
|
658 if (node.response != undefined) {
|
nickjillings@1361
|
659 input.value = node.response;
|
nickjillings@1361
|
660 }
|
nickjillings@1526
|
661 this.popupResponse.appendChild(input);
|
nickjillings@1382
|
662 this.popupResponse.style.textAlign="center";
|
nickjillings@1382
|
663 this.popupResponse.style.left="0%";
|
nickjillings@1622
|
664 }
|
nickjillings@2034
|
665 if(this.currentIndex+1 == this.popupOptions.length) {
|
nickjillings@1324
|
666 if (this.node.location == "pre") {
|
nickjillings@1531
|
667 this.buttonProceed.textContent = 'Start';
|
nickjillings@1531
|
668 } else {
|
nickjillings@1531
|
669 this.buttonProceed.textContent = 'Submit';
|
nickjillings@1531
|
670 }
|
nickjillings@2034
|
671 } else {
|
nickjillings@2034
|
672 this.buttonProceed.textContent = 'Next';
|
nickjillings@2034
|
673 }
|
nickjillings@2034
|
674 if(this.currentIndex > 0)
|
nickjillings@1526
|
675 this.buttonPrevious.style.visibility = 'visible';
|
nickjillings@1526
|
676 else
|
nickjillings@1526
|
677 this.buttonPrevious.style.visibility = 'hidden';
|
nickjillings@2015
|
678 };
|
nickjillings@1622
|
679
|
nickjillings@1324
|
680 this.initState = function(node,store) {
|
nickjillings@1622
|
681 //Call this with your preTest and postTest nodes when needed to
|
nickjillings@1622
|
682 // initialise the popup procedure.
|
nickjillings@1324
|
683 if (node.options.length > 0) {
|
nickjillings@1324
|
684 this.popupOptions = [];
|
nickjillings@1324
|
685 this.node = node;
|
nickjillings@1324
|
686 this.store = store;
|
nickjillings@1324
|
687 for (var opt of node.options)
|
nickjillings@1324
|
688 {
|
nickjillings@1324
|
689 this.popupOptions.push({
|
nickjillings@1324
|
690 specification: opt,
|
nickjillings@1324
|
691 response: null
|
nickjillings@1324
|
692 });
|
nickjillings@1324
|
693 }
|
nickjillings@1622
|
694 this.currentIndex = 0;
|
nickjillings@1622
|
695 this.showPopup();
|
nickjillings@1622
|
696 this.postNode();
|
nickjillings@1581
|
697 } else {
|
nickjillings@1581
|
698 advanceState();
|
nickjillings@1622
|
699 }
|
nickjillings@2015
|
700 };
|
nickjillings@1622
|
701
|
nickjillings@1574
|
702 this.proceedClicked = function() {
|
nickjillings@1622
|
703 // Each time the popup button is clicked!
|
nickjillings@1622
|
704 var node = this.popupOptions[this.currentIndex];
|
nickjillings@1324
|
705 if (node.specification.type == 'question') {
|
nickjillings@1622
|
706 // Must extract the question data
|
nickjillings@1622
|
707 var textArea = $(popup.popupContent).find('textarea')[0];
|
nickjillings@1324
|
708 if (node.specification.mandatory == true && textArea.value.length == 0) {
|
nickjillings@1622
|
709 alert('This question is mandatory');
|
nickjillings@1622
|
710 return;
|
nickjillings@1622
|
711 } else {
|
nickjillings@1622
|
712 // Save the text content
|
nickjillings@1324
|
713 console.log("Question: "+ node.specification.statement);
|
nickjillings@1623
|
714 console.log("Question Response: "+ textArea.value);
|
nickjillings@1324
|
715 node.response = textArea.value;
|
nickjillings@1622
|
716 }
|
nickjillings@1324
|
717 } else if (node.specification.type == 'checkbox') {
|
nickjillings@1588
|
718 // Must extract checkbox data
|
nickjillings@1326
|
719 console.log("Checkbox: "+ node.specification.statement);
|
nickjillings@1324
|
720 var inputs = this.popupResponse.getElementsByTagName('input');
|
nickjillings@1324
|
721 node.response = [];
|
nickjillings@1324
|
722 for (var i=0; i<node.specification.options.length; i++) {
|
nickjillings@1324
|
723 node.response.push({
|
nickjillings@1324
|
724 name: node.specification.options[i].name,
|
nickjillings@1324
|
725 text: node.specification.options[i].text,
|
nickjillings@1324
|
726 checked: inputs[i].checked
|
nickjillings@1324
|
727 });
|
nickjillings@1326
|
728 console.log(node.specification.options[i].name+": "+ inputs[i].checked);
|
nickjillings@1324
|
729 }
|
nickjillings@1324
|
730 } else if (node.specification.type == "radio") {
|
nickjillings@1526
|
731 var optHold = this.popupResponse;
|
nickjillings@1324
|
732 console.log("Radio: "+ node.specification.statement);
|
nickjillings@1324
|
733 node.response = null;
|
nickjillings@1589
|
734 var i=0;
|
nickjillings@1324
|
735 var inputs = optHold.getElementsByTagName('input');
|
nickjillings@1324
|
736 while(node.response == null) {
|
nickjillings@1324
|
737 if (i == inputs.length)
|
nickjillings@1324
|
738 {
|
nickjillings@1324
|
739 if (node.specification.mandatory == true)
|
nickjillings@1324
|
740 {
|
nickjillings@1324
|
741 alert("This radio is mandatory");
|
nickjillings@1324
|
742 } else {
|
nickjillings@1324
|
743 node.response = -1;
|
nickjillings@1324
|
744 }
|
nickjillings@1324
|
745 return;
|
nickjillings@1324
|
746 }
|
nickjillings@1324
|
747 if (inputs[i].checked == true) {
|
nickjillings@1324
|
748 node.response = node.specification.options[i];
|
nickjillings@1324
|
749 console.log("Selected: "+ node.specification.options[i].name);
|
nickjillings@1589
|
750 }
|
nickjillings@1589
|
751 i++;
|
nickjillings@1589
|
752 }
|
nickjillings@1324
|
753 } else if (node.specification.type == "number") {
|
nickjillings@1573
|
754 var input = this.popupContent.getElementsByTagName('input')[0];
|
nickjillings@1573
|
755 if (node.mandatory == true && input.value.length == 0) {
|
nickjillings@1574
|
756 alert('This question is mandatory. Please enter a number');
|
nickjillings@1574
|
757 return;
|
nickjillings@1574
|
758 }
|
nickjillings@1574
|
759 var enteredNumber = Number(input.value);
|
nickjillings@2044
|
760 if (isNaN(enteredNumber)) {
|
nickjillings@1574
|
761 alert('Please enter a valid number');
|
nickjillings@1574
|
762 return;
|
nickjillings@1574
|
763 }
|
nickjillings@1574
|
764 if (enteredNumber < node.min && node.min != null) {
|
nickjillings@1574
|
765 alert('Number is below the minimum value of '+node.min);
|
nickjillings@1574
|
766 return;
|
nickjillings@1574
|
767 }
|
nickjillings@1574
|
768 if (enteredNumber > node.max && node.max != null) {
|
nickjillings@1574
|
769 alert('Number is above the maximum value of '+node.max);
|
nickjillings@1573
|
770 return;
|
nickjillings@1573
|
771 }
|
nickjillings@1324
|
772 node.response = input.value;
|
nickjillings@1622
|
773 }
|
nickjillings@1622
|
774 this.currentIndex++;
|
nickjillings@1622
|
775 if (this.currentIndex < this.popupOptions.length) {
|
nickjillings@1622
|
776 this.postNode();
|
nickjillings@1622
|
777 } else {
|
nickjillings@1622
|
778 // Reached the end of the popupOptions
|
nickjillings@1622
|
779 this.hidePopup();
|
nickjillings@1324
|
780 for (var node of this.popupOptions)
|
nickjillings@1324
|
781 {
|
nickjillings@1324
|
782 this.store.postResult(node);
|
nickjillings@1634
|
783 }
|
nickjillings@1294
|
784 this.store.complete();
|
nickjillings@1622
|
785 advanceState();
|
nickjillings@1622
|
786 }
|
nickjillings@2015
|
787 };
|
nickjillings@2034
|
788
|
nickjillings@2034
|
789 this.previousClick = function() {
|
nickjillings@2034
|
790 // Triggered when the 'Back' button is clicked in the survey
|
nickjillings@2034
|
791 if (this.currentIndex > 0) {
|
nickjillings@2034
|
792 this.currentIndex--;
|
nickjillings@2034
|
793 this.postNode();
|
nickjillings@2034
|
794 }
|
nickjillings@2034
|
795 };
|
nickjillings@1421
|
796
|
nickjillings@1421
|
797 this.resize = function(event)
|
nickjillings@1421
|
798 {
|
nickjillings@1421
|
799 // Called on window resize;
|
nickjillings@1344
|
800 if (this.popup != null) {
|
nickjillings@1344
|
801 this.popup.style.left = (window.innerWidth/2)-250 + 'px';
|
nickjillings@1344
|
802 this.popup.style.top = (window.innerHeight/2)-125 + 'px';
|
nickjillings@1344
|
803 var blank = document.getElementsByClassName('testHalt')[0];
|
nickjillings@1344
|
804 blank.style.width = window.innerWidth;
|
nickjillings@1344
|
805 blank.style.height = window.innerHeight;
|
nickjillings@1344
|
806 }
|
nickjillings@1421
|
807 };
|
nickjillings@2106
|
808 this.hideNextButton = function() {
|
nickjillings@2106
|
809 this.buttonProceed.style.visibility = "hidden";
|
nickjillings@2106
|
810 }
|
nickjillings@2106
|
811 this.hidePreviousButton = function() {
|
nickjillings@2106
|
812 this.buttonPrevious.style.visibility = "hidden";
|
nickjillings@2106
|
813 }
|
nickjillings@2106
|
814 this.showNextButton = function() {
|
nickjillings@2106
|
815 this.buttonProceed.style.visibility = "visible";
|
nickjillings@2106
|
816 }
|
nickjillings@2106
|
817 this.showPreviousButton = function() {
|
nickjillings@2106
|
818 this.buttonPrevious.style.visibility = "visible";
|
nickjillings@2106
|
819 }
|
nickjillings@1621
|
820 }
|
nickjillings@1621
|
821
|
nickjillings@1622
|
822 function advanceState()
|
nickjillings@1621
|
823 {
|
nickjillings@1634
|
824 // Just for complete clarity
|
nickjillings@1634
|
825 testState.advanceState();
|
nickjillings@1634
|
826 }
|
nickjillings@1634
|
827
|
nickjillings@1634
|
828 function stateMachine()
|
nickjillings@1634
|
829 {
|
nickjillings@1634
|
830 // Object prototype for tracking and managing the test state
|
nickjillings@1634
|
831 this.stateMap = [];
|
nickjillings@1324
|
832 this.preTestSurvey = null;
|
nickjillings@1324
|
833 this.postTestSurvey = null;
|
nickjillings@1634
|
834 this.stateIndex = null;
|
nickjillings@1324
|
835 this.currentStateMap = null;
|
nickjillings@1324
|
836 this.currentStatePosition = null;
|
nickjillings@1354
|
837 this.currentStore = null;
|
nickjillings@1634
|
838 this.initialise = function(){
|
nickjillings@1324
|
839
|
nickjillings@1324
|
840 // Get the data from Specification
|
nickjillings@1324
|
841 var pageHolder = [];
|
nickjillings@1324
|
842 for (var page of specification.pages)
|
nickjillings@1324
|
843 {
|
nickjillings@1380
|
844 var repeat = page.repeatCount;
|
nickjillings@1380
|
845 while(repeat >= 0)
|
nickjillings@1380
|
846 {
|
nickjillings@1380
|
847 pageHolder.push(page);
|
nickjillings@1380
|
848 repeat--;
|
nickjillings@1380
|
849 }
|
nickjillings@1324
|
850 }
|
nickjillings@1324
|
851 if (specification.randomiseOrder)
|
nickjillings@1324
|
852 {
|
nickjillings@1324
|
853 pageHolder = randomiseOrder(pageHolder);
|
nickjillings@1324
|
854 }
|
nickjillings@1324
|
855 for (var i=0; i<pageHolder.length; i++)
|
nickjillings@1324
|
856 {
|
nickjillings@2124
|
857 if (specification.testPages <= i && specification.testPages != 0) {break;}
|
nickjillings@2169
|
858 pageHolder[i].presentedId = i;
|
nickjillings@1324
|
859 this.stateMap.push(pageHolder[i]);
|
nickjillings@2149
|
860 storage.createTestPageStore(pageHolder[i]);
|
nickjillings@2152
|
861 for (var element of pageHolder[i].audioElements) {
|
nickjillings@2152
|
862 var URL = pageHolder[i].hostURL + element.url;
|
nickjillings@2152
|
863 var buffer = null;
|
nickjillings@2152
|
864 for (var buffObj of audioEngineContext.buffers) {
|
nickjillings@2152
|
865 if (URL == buffObj.url) {
|
nickjillings@2152
|
866 buffer = buffObj;
|
nickjillings@2152
|
867 break;
|
nickjillings@2152
|
868 }
|
nickjillings@2152
|
869 }
|
nickjillings@2152
|
870 if (buffer == null) {
|
nickjillings@2152
|
871 buffer = new audioEngineContext.bufferObj();
|
nickjillings@2152
|
872 buffer.getMedia(URL);
|
nickjillings@2152
|
873 audioEngineContext.buffers.push(buffer);
|
nickjillings@2152
|
874 }
|
nickjillings@2152
|
875 }
|
nickjillings@1324
|
876 }
|
nickjillings@2124
|
877
|
nickjillings@1324
|
878 if (specification.preTest != null) {this.preTestSurvey = specification.preTest;}
|
nickjillings@1324
|
879 if (specification.postTest != null) {this.postTestSurvey = specification.postTest;}
|
nickjillings@1324
|
880
|
nickjillings@1634
|
881 if (this.stateMap.length > 0) {
|
nickjillings@1634
|
882 if(this.stateIndex != null) {
|
nickjillings@1634
|
883 console.log('NOTE - State already initialise');
|
nickjillings@1634
|
884 }
|
nickjillings@1634
|
885 this.stateIndex = -1;
|
nickjillings@1634
|
886 } else {
|
b@2059
|
887 console.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP');
|
nickjillings@1622
|
888 }
|
nickjillings@1634
|
889 };
|
nickjillings@1634
|
890 this.advanceState = function(){
|
nickjillings@1634
|
891 if (this.stateIndex == null) {
|
nickjillings@1634
|
892 this.initialise();
|
nickjillings@1634
|
893 }
|
nickjillings@2150
|
894 storage.update();
|
nickjillings@1634
|
895 if (this.stateIndex == -1) {
|
nickjillings@1342
|
896 this.stateIndex++;
|
nickjillings@1634
|
897 console.log('Starting test...');
|
nickjillings@1324
|
898 if (this.preTestSurvey != null)
|
nickjillings@1324
|
899 {
|
nickjillings@1324
|
900 popup.initState(this.preTestSurvey,storage.globalPreTest);
|
nickjillings@1342
|
901 } else {
|
nickjillings@1342
|
902 this.advanceState();
|
nickjillings@1318
|
903 }
|
nickjillings@1324
|
904 } else if (this.stateIndex == this.stateMap.length)
|
nickjillings@1324
|
905 {
|
nickjillings@1324
|
906 // All test pages complete, post test
|
nickjillings@1324
|
907 console.log('Ending test ...');
|
nickjillings@1324
|
908 this.stateIndex++;
|
nickjillings@1324
|
909 if (this.postTestSurvey == null) {
|
nickjillings@1324
|
910 this.advanceState();
|
nickjillings@1318
|
911 } else {
|
nickjillings@1324
|
912 popup.initState(this.postTestSurvey,storage.globalPostTest);
|
nickjillings@1324
|
913 }
|
nickjillings@1324
|
914 } else if (this.stateIndex > this.stateMap.length)
|
nickjillings@1324
|
915 {
|
nickjillings@1324
|
916 createProjectSave(specification.projectReturn);
|
nickjillings@1634
|
917 }
|
nickjillings@1324
|
918 else
|
nickjillings@1324
|
919 {
|
nickjillings@1324
|
920 if (this.currentStateMap == null)
|
nickjillings@1324
|
921 {
|
nickjillings@1318
|
922 this.currentStateMap = this.stateMap[this.stateIndex];
|
nickjillings@1334
|
923 if (this.currentStateMap.randomiseOrder)
|
nickjillings@1334
|
924 {
|
nickjillings@1334
|
925 this.currentStateMap.audioElements = randomiseOrder(this.currentStateMap.audioElements);
|
nickjillings@1334
|
926 }
|
nickjillings@2149
|
927 this.currentStore = storage.testPages[this.stateIndex];
|
nickjillings@1324
|
928 if (this.currentStateMap.preTest != null)
|
nickjillings@1324
|
929 {
|
nickjillings@1324
|
930 this.currentStatePosition = 'pre';
|
nickjillings@1324
|
931 popup.initState(this.currentStateMap.preTest,storage.testPages[this.stateIndex].preTest);
|
nickjillings@1318
|
932 } else {
|
nickjillings@1324
|
933 this.currentStatePosition = 'test';
|
nickjillings@1324
|
934 }
|
nickjillings@1324
|
935 interfaceContext.newPage(this.currentStateMap,storage.testPages[this.stateIndex]);
|
nickjillings@1324
|
936 return;
|
nickjillings@1634
|
937 }
|
nickjillings@1324
|
938 switch(this.currentStatePosition)
|
nickjillings@1324
|
939 {
|
nickjillings@1324
|
940 case 'pre':
|
nickjillings@1324
|
941 this.currentStatePosition = 'test';
|
nickjillings@1324
|
942 break;
|
nickjillings@1324
|
943 case 'test':
|
nickjillings@1324
|
944 this.currentStatePosition = 'post';
|
nickjillings@1324
|
945 // Save the data
|
nickjillings@1324
|
946 this.testPageCompleted();
|
nickjillings@1324
|
947 if (this.currentStateMap.postTest == null)
|
nickjillings@1324
|
948 {
|
nickjillings@1318
|
949 this.advanceState();
|
nickjillings@1324
|
950 return;
|
nickjillings@1634
|
951 } else {
|
nickjillings@1324
|
952 popup.initState(this.currentStateMap.postTest,storage.testPages[this.stateIndex].postTest);
|
nickjillings@1634
|
953 }
|
nickjillings@1324
|
954 break;
|
nickjillings@1324
|
955 case 'post':
|
nickjillings@1324
|
956 this.stateIndex++;
|
nickjillings@1324
|
957 this.currentStateMap = null;
|
nickjillings@1324
|
958 this.advanceState();
|
nickjillings@1324
|
959 break;
|
nickjillings@1324
|
960 };
|
nickjillings@1634
|
961 }
|
nickjillings@1634
|
962 };
|
nickjillings@1634
|
963
|
nickjillings@1324
|
964 this.testPageCompleted = function() {
|
nickjillings@1634
|
965 // Function called each time a test page has been completed
|
nickjillings@1324
|
966 var storePoint = storage.testPages[this.stateIndex];
|
nickjillings@1324
|
967 // First get the test metric
|
nickjillings@1324
|
968
|
nickjillings@1324
|
969 var metric = storePoint.XMLDOM.getElementsByTagName('metric')[0];
|
nickjillings@1412
|
970 if (audioEngineContext.metric.enableTestTimer)
|
nickjillings@1412
|
971 {
|
nickjillings@1324
|
972 var testTime = storePoint.parent.document.createElement('metricresult');
|
nickjillings@1412
|
973 testTime.id = 'testTime';
|
nickjillings@1412
|
974 testTime.textContent = audioEngineContext.timer.testDuration;
|
nickjillings@1412
|
975 metric.appendChild(testTime);
|
nickjillings@1412
|
976 }
|
nickjillings@1324
|
977
|
nickjillings@1412
|
978 var audioObjects = audioEngineContext.audioObjects;
|
nickjillings@1324
|
979 for (var ao of audioEngineContext.audioObjects)
|
nickjillings@1412
|
980 {
|
nickjillings@1324
|
981 ao.exportXMLDOM();
|
nickjillings@1412
|
982 }
|
nickjillings@1324
|
983 for (var element of interfaceContext.commentQuestions)
|
nickjillings@1324
|
984 {
|
nickjillings@1324
|
985 element.exportXMLDOM(storePoint);
|
nickjillings@1324
|
986 }
|
nickjillings@1324
|
987 pageXMLSave(storePoint.XMLDOM, this.currentStateMap);
|
nickjillings@1294
|
988 storePoint.complete();
|
nickjillings@1576
|
989 };
|
nickjillings@1621
|
990 }
|
nickjillings@1621
|
991
|
nickjillings@1408
|
992 function AudioEngine(specification) {
|
nickjillings@1682
|
993
|
nickjillings@1682
|
994 // Create two output paths, the main outputGain and fooGain.
|
nickjillings@1682
|
995 // Output gain is default to 1 and any items for playback route here
|
nickjillings@1682
|
996 // Foo gain is used for analysis to ensure paths get processed, but are not heard
|
nickjillings@1682
|
997 // because web audio will optimise and any route which does not go to the destination gets ignored.
|
nickjillings@1682
|
998 this.outputGain = audioContext.createGain();
|
nickjillings@1682
|
999 this.fooGain = audioContext.createGain();
|
nickjillings@1682
|
1000 this.fooGain.gain = 0;
|
nickjillings@1682
|
1001
|
nickjillings@1688
|
1002 // Use this to detect playback state: 0 - stopped, 1 - playing
|
nickjillings@1688
|
1003 this.status = 0;
|
nickjillings@1688
|
1004
|
nickjillings@1682
|
1005 // Connect both gains to output
|
nickjillings@1682
|
1006 this.outputGain.connect(audioContext.destination);
|
nickjillings@1682
|
1007 this.fooGain.connect(audioContext.destination);
|
nickjillings@1682
|
1008
|
nickjillings@1659
|
1009 // Create the timer Object
|
nickjillings@1659
|
1010 this.timer = new timer();
|
nickjillings@1659
|
1011 // Create session metrics
|
nickjillings@1408
|
1012 this.metric = new sessionMetrics(this,specification);
|
nickjillings@1659
|
1013
|
nickjillings@1667
|
1014 this.loopPlayback = false;
|
nickjillings@1667
|
1015
|
nickjillings@1324
|
1016 this.pageStore = null;
|
nickjillings@1324
|
1017
|
nickjillings@1682
|
1018 // Create store for new audioObjects
|
nickjillings@1682
|
1019 this.audioObjects = [];
|
nickjillings@1682
|
1020
|
nickjillings@1410
|
1021 this.buffers = [];
|
nickjillings@1430
|
1022 this.bufferObj = function()
|
nickjillings@1410
|
1023 {
|
nickjillings@1430
|
1024 this.url = null;
|
nickjillings@1410
|
1025 this.buffer = null;
|
nickjillings@1410
|
1026 this.xmlRequest = new XMLHttpRequest();
|
nickjillings@1396
|
1027 this.xmlRequest.parent = this;
|
nickjillings@1410
|
1028 this.users = [];
|
nickjillings@1316
|
1029 this.progress = 0;
|
nickjillings@1316
|
1030 this.status = 0;
|
nickjillings@1342
|
1031 this.ready = function()
|
nickjillings@1342
|
1032 {
|
nickjillings@1316
|
1033 if (this.status >= 2)
|
nickjillings@1316
|
1034 {
|
nickjillings@1316
|
1035 this.status = 3;
|
nickjillings@1316
|
1036 }
|
nickjillings@1342
|
1037 for (var i=0; i<this.users.length; i++)
|
nickjillings@1342
|
1038 {
|
nickjillings@1342
|
1039 this.users[i].state = 1;
|
nickjillings@1342
|
1040 if (this.users[i].interfaceDOM != null)
|
nickjillings@1342
|
1041 {
|
nickjillings@1342
|
1042 this.users[i].bufferLoaded(this);
|
nickjillings@1342
|
1043 }
|
nickjillings@1342
|
1044 }
|
nickjillings@1342
|
1045 };
|
nickjillings@1430
|
1046 this.getMedia = function(url) {
|
nickjillings@1430
|
1047 this.url = url;
|
nickjillings@1430
|
1048 this.xmlRequest.open('GET',this.url,true);
|
nickjillings@1430
|
1049 this.xmlRequest.responseType = 'arraybuffer';
|
nickjillings@1430
|
1050
|
nickjillings@1430
|
1051 var bufferObj = this;
|
nickjillings@1430
|
1052
|
nickjillings@1430
|
1053 // Create callback to decode the data asynchronously
|
nickjillings@1430
|
1054 this.xmlRequest.onloadend = function() {
|
nickjillings@1353
|
1055 // Use inbuilt WAVE decoder first
|
nickjillings@2113
|
1056 if (this.status == -1) {return;}
|
nickjillings@1353
|
1057 var waveObj = new WAVE();
|
nickjillings@1353
|
1058 if (waveObj.open(bufferObj.xmlRequest.response) == 0)
|
nickjillings@1353
|
1059 {
|
nickjillings@1353
|
1060 bufferObj.buffer = audioContext.createBuffer(waveObj.num_channels,waveObj.num_samples,waveObj.sample_rate);
|
nickjillings@1353
|
1061 for (var c=0; c<waveObj.num_channels; c++)
|
nickjillings@1353
|
1062 {
|
nickjillings@1353
|
1063 var buffer_ptr = bufferObj.buffer.getChannelData(c);
|
nickjillings@1353
|
1064 for (var n=0; n<waveObj.num_samples; n++)
|
nickjillings@1353
|
1065 {
|
nickjillings@1353
|
1066 buffer_ptr[n] = waveObj.decoded_data[c][n];
|
nickjillings@1353
|
1067 }
|
nickjillings@1353
|
1068 }
|
nickjillings@1316
|
1069
|
nickjillings@1353
|
1070 delete waveObj;
|
nickjillings@1353
|
1071 } else {
|
nickjillings@1353
|
1072 audioContext.decodeAudioData(bufferObj.xmlRequest.response, function(decodedData) {
|
nickjillings@1353
|
1073 bufferObj.buffer = decodedData;
|
nickjillings@1353
|
1074 }, function(e){
|
nickjillings@1353
|
1075 // Should only be called if there was an error, but sometimes gets called continuously
|
nickjillings@1353
|
1076 // Check here if the error is genuine
|
nickjillings@1353
|
1077 if (bufferObj.xmlRequest.response == undefined) {
|
nickjillings@1353
|
1078 // Genuine error
|
nickjillings@1353
|
1079 console.log('FATAL - Error loading buffer on '+audioObj.id);
|
nickjillings@1353
|
1080 if (request.status == 404)
|
nickjillings@1353
|
1081 {
|
nickjillings@1353
|
1082 console.log('FATAL - Fragment '+audioObj.id+' 404 error');
|
nickjillings@1353
|
1083 console.log('URL: '+audioObj.url);
|
nickjillings@1353
|
1084 errorSessionDump('Fragment '+audioObj.id+' 404 error');
|
nickjillings@1353
|
1085 }
|
nickjillings@2113
|
1086 this.parent.status = -1;
|
nickjillings@1353
|
1087 }
|
nickjillings@1353
|
1088 });
|
nickjillings@1353
|
1089 }
|
nickjillings@1353
|
1090 if (bufferObj.buffer != undefined)
|
nickjillings@1353
|
1091 {
|
nickjillings@1316
|
1092 bufferObj.status = 2;
|
nickjillings@1353
|
1093 calculateLoudness(bufferObj,"I");
|
nickjillings@1353
|
1094 }
|
nickjillings@1430
|
1095 };
|
nickjillings@2113
|
1096
|
nickjillings@2113
|
1097 // Create callback for any error in loading
|
nickjillings@2113
|
1098 this.xmlRequest.onerror = function() {
|
nickjillings@2113
|
1099 this.parent.status = -1;
|
nickjillings@2113
|
1100 for (var i=0; i<this.parent.users.length; i++)
|
nickjillings@2113
|
1101 {
|
nickjillings@2113
|
1102 this.parent.users[i].state = -1;
|
nickjillings@2113
|
1103 if (this.parent.users[i].interfaceDOM != null)
|
nickjillings@2113
|
1104 {
|
nickjillings@2113
|
1105 this.parent.users[i].bufferLoaded(this);
|
nickjillings@2113
|
1106 }
|
nickjillings@2113
|
1107 }
|
nickjillings@2113
|
1108 }
|
nickjillings@2113
|
1109
|
nickjillings@1433
|
1110 this.progress = 0;
|
nickjillings@1433
|
1111 this.progressCallback = function(event){
|
nickjillings@1433
|
1112 if (event.lengthComputable)
|
nickjillings@1433
|
1113 {
|
nickjillings@1396
|
1114 this.parent.progress = event.loaded / event.total;
|
nickjillings@1396
|
1115 for (var i=0; i<this.parent.users.length; i++)
|
nickjillings@1396
|
1116 {
|
nickjillings@1396
|
1117 if(this.parent.users[i].interfaceDOM != null)
|
nickjillings@1396
|
1118 {
|
nickjillings@1396
|
1119 if (typeof this.parent.users[i].interfaceDOM.updateLoading === "function")
|
nickjillings@1396
|
1120 {
|
nickjillings@1396
|
1121 this.parent.users[i].interfaceDOM.updateLoading(this.parent.progress*100);
|
nickjillings@1396
|
1122 }
|
nickjillings@1396
|
1123 }
|
nickjillings@1396
|
1124 }
|
nickjillings@1433
|
1125 }
|
nickjillings@1433
|
1126 };
|
nickjillings@1433
|
1127 this.xmlRequest.addEventListener("progress", this.progressCallback);
|
nickjillings@1316
|
1128 this.status = 1;
|
nickjillings@1430
|
1129 this.xmlRequest.send();
|
nickjillings@1410
|
1130 };
|
nickjillings@1316
|
1131
|
nickjillings@1316
|
1132 this.registerAudioObject = function(audioObject)
|
nickjillings@1316
|
1133 {
|
nickjillings@1316
|
1134 // Called by an audioObject to register to the buffer for use
|
nickjillings@1316
|
1135 // First check if already in the register pool
|
nickjillings@1316
|
1136 for (var objects of this.users)
|
nickjillings@1316
|
1137 {
|
nickjillings@1316
|
1138 if (audioObject.id == objects.id){return 0;}
|
nickjillings@1316
|
1139 }
|
nickjillings@1316
|
1140 this.users.push(audioObject);
|
nickjillings@2113
|
1141 if (this.status == 3 || this.status == -1)
|
nickjillings@1316
|
1142 {
|
nickjillings@1316
|
1143 // The buffer is already ready, trigger bufferLoaded
|
nickjillings@1316
|
1144 audioObject.bufferLoaded(this);
|
nickjillings@1316
|
1145 }
|
nickjillings@1316
|
1146 }
|
nickjillings@1410
|
1147 };
|
nickjillings@1410
|
1148
|
nickjillings@1565
|
1149 this.play = function(id) {
|
nickjillings@1620
|
1150 // Start the timer and set the audioEngine state to playing (1)
|
nickjillings@1523
|
1151 if (this.status == 0 && this.loopPlayback) {
|
nickjillings@1620
|
1152 // Check if all audioObjects are ready
|
nickjillings@1523
|
1153 if(this.checkAllReady())
|
nickjillings@1523
|
1154 {
|
nickjillings@1565
|
1155 this.status = 1;
|
nickjillings@1523
|
1156 this.setSynchronousLoop();
|
nickjillings@1565
|
1157 }
|
nickjillings@1565
|
1158 }
|
nickjillings@1523
|
1159 else
|
nickjillings@1523
|
1160 {
|
nickjillings@1523
|
1161 this.status = 1;
|
nickjillings@1523
|
1162 }
|
nickjillings@1565
|
1163 if (this.status== 1) {
|
nickjillings@1523
|
1164 this.timer.startTest();
|
nickjillings@1567
|
1165 if (id == undefined) {
|
nickjillings@1567
|
1166 id = -1;
|
nickjillings@1523
|
1167 console.log('FATAL - Passed id was undefined - AudioEngineContext.play(id)');
|
nickjillings@1523
|
1168 return;
|
nickjillings@1567
|
1169 } else {
|
nickjillings@1567
|
1170 interfaceContext.playhead.setTimePerPixel(this.audioObjects[id]);
|
nickjillings@1567
|
1171 }
|
nickjillings@1565
|
1172 if (this.loopPlayback) {
|
nickjillings@2099
|
1173 var setTime = audioContext.currentTime;
|
nickjillings@1565
|
1174 for (var i=0; i<this.audioObjects.length; i++)
|
nickjillings@1565
|
1175 {
|
nickjillings@2099
|
1176 this.audioObjects[i].play(setTime);
|
nickjillings@1565
|
1177 if (id == i) {
|
nickjillings@1360
|
1178 this.audioObjects[i].loopStart(setTime);
|
nickjillings@1565
|
1179 } else {
|
nickjillings@1360
|
1180 this.audioObjects[i].loopStop(setTime);
|
nickjillings@1636
|
1181 }
|
nickjillings@1636
|
1182 }
|
nickjillings@1565
|
1183 } else {
|
nickjillings@1360
|
1184 var setTime = audioContext.currentTime+0.1;
|
nickjillings@1565
|
1185 for (var i=0; i<this.audioObjects.length; i++)
|
nickjillings@1565
|
1186 {
|
nickjillings@1565
|
1187 if (i != id) {
|
nickjillings@1360
|
1188 this.audioObjects[i].stop(setTime);
|
nickjillings@1565
|
1189 } else if (i == id) {
|
nickjillings@1360
|
1190 this.audioObjects[id].play(setTime);
|
nickjillings@1565
|
1191 }
|
nickjillings@1565
|
1192 }
|
nickjillings@1620
|
1193 }
|
nickjillings@1567
|
1194 interfaceContext.playhead.start();
|
nickjillings@1620
|
1195 }
|
nickjillings@1620
|
1196 };
|
nickjillings@1682
|
1197
|
nickjillings@1620
|
1198 this.stop = function() {
|
nickjillings@1378
|
1199 // Send stop and reset command to all playback buffers
|
nickjillings@1620
|
1200 if (this.status == 1) {
|
nickjillings@1360
|
1201 var setTime = audioContext.currentTime+0.1;
|
nickjillings@1620
|
1202 for (var i=0; i<this.audioObjects.length; i++)
|
nickjillings@1620
|
1203 {
|
nickjillings@1360
|
1204 this.audioObjects[i].stop(setTime);
|
nickjillings@1620
|
1205 }
|
nickjillings@1567
|
1206 interfaceContext.playhead.stop();
|
nickjillings@1620
|
1207 }
|
nickjillings@1620
|
1208 };
|
nickjillings@1689
|
1209
|
nickjillings@1582
|
1210 this.newTrack = function(element) {
|
nickjillings@1682
|
1211 // Pull data from given URL into new audio buffer
|
nickjillings@1682
|
1212 // URLs must either be from the same source OR be setup to 'Access-Control-Allow-Origin'
|
nickjillings@1688
|
1213
|
nickjillings@1682
|
1214 // Create the audioObject with ID of the new track length;
|
nickjillings@1659
|
1215 audioObjectId = this.audioObjects.length;
|
nickjillings@1682
|
1216 this.audioObjects[audioObjectId] = new audioObject(audioObjectId);
|
nickjillings@1688
|
1217
|
nickjillings@1410
|
1218 // Check if audioObject buffer is currently stored by full URL
|
nickjillings@1324
|
1219 var URL = testState.currentStateMap.hostURL + element.url;
|
nickjillings@1410
|
1220 var buffer = null;
|
nickjillings@1410
|
1221 for (var i=0; i<this.buffers.length; i++)
|
nickjillings@1410
|
1222 {
|
nickjillings@1410
|
1223 if (URL == this.buffers[i].url)
|
nickjillings@1410
|
1224 {
|
nickjillings@1410
|
1225 buffer = this.buffers[i];
|
nickjillings@1410
|
1226 break;
|
nickjillings@1410
|
1227 }
|
nickjillings@1410
|
1228 }
|
nickjillings@1410
|
1229 if (buffer == null)
|
nickjillings@1410
|
1230 {
|
nickjillings@1426
|
1231 console.log("[WARN]: Buffer was not loaded in pre-test! "+URL);
|
nickjillings@1430
|
1232 buffer = new this.bufferObj();
|
nickjillings@1316
|
1233 this.buffers.push(buffer);
|
nickjillings@1430
|
1234 buffer.getMedia(URL);
|
nickjillings@1410
|
1235 }
|
nickjillings@1582
|
1236 this.audioObjects[audioObjectId].specification = element;
|
nickjillings@1426
|
1237 this.audioObjects[audioObjectId].url = URL;
|
nickjillings@1324
|
1238 // Obtain store node
|
nickjillings@1324
|
1239 var aeNodes = this.pageStore.XMLDOM.getElementsByTagName('audioelement');
|
nickjillings@1324
|
1240 for (var i=0; i<aeNodes.length; i++)
|
nickjillings@1410
|
1241 {
|
nickjillings@1294
|
1242 if(aeNodes[i].getAttribute("ref") == element.id)
|
nickjillings@1324
|
1243 {
|
nickjillings@1324
|
1244 this.audioObjects[audioObjectId].storeDOM = aeNodes[i];
|
nickjillings@1324
|
1245 break;
|
nickjillings@1324
|
1246 }
|
nickjillings@1410
|
1247 }
|
nickjillings@1316
|
1248 buffer.registerAudioObject(this.audioObjects[audioObjectId]);
|
nickjillings@1579
|
1249 return this.audioObjects[audioObjectId];
|
nickjillings@1697
|
1250 };
|
nickjillings@1682
|
1251
|
nickjillings@1369
|
1252 this.newTestPage = function(audioHolderObject,store) {
|
nickjillings@1324
|
1253 this.pageStore = store;
|
nickjillings@2127
|
1254 this.status = 0;
|
nickjillings@1620
|
1255 this.audioObjectsReady = false;
|
nickjillings@1620
|
1256 this.metric.reset();
|
nickjillings@1410
|
1257 for (var i=0; i < this.buffers.length; i++)
|
nickjillings@1410
|
1258 {
|
nickjillings@1410
|
1259 this.buffers[i].users = [];
|
nickjillings@1410
|
1260 }
|
nickjillings@1620
|
1261 this.audioObjects = [];
|
nickjillings@1369
|
1262 this.timer = new timer();
|
nickjillings@1369
|
1263 this.loopPlayback = audioHolderObject.loop;
|
nickjillings@1620
|
1264 };
|
nickjillings@1620
|
1265
|
nickjillings@1614
|
1266 this.checkAllPlayed = function() {
|
nickjillings@1614
|
1267 arr = [];
|
nickjillings@1614
|
1268 for (var id=0; id<this.audioObjects.length; id++) {
|
nickjillings@2008
|
1269 if (this.audioObjects[id].metric.wasListenedTo == false) {
|
nickjillings@1614
|
1270 arr.push(this.audioObjects[id].id);
|
nickjillings@1614
|
1271 }
|
nickjillings@1614
|
1272 }
|
nickjillings@1614
|
1273 return arr;
|
nickjillings@1614
|
1274 };
|
nickjillings@1614
|
1275
|
nickjillings@1620
|
1276 this.checkAllReady = function() {
|
nickjillings@1620
|
1277 var ready = true;
|
nickjillings@1620
|
1278 for (var i=0; i<this.audioObjects.length; i++) {
|
nickjillings@1620
|
1279 if (this.audioObjects[i].state == 0) {
|
nickjillings@1620
|
1280 // Track not ready
|
nickjillings@1620
|
1281 console.log('WAIT -- audioObject '+i+' not ready yet!');
|
nickjillings@1620
|
1282 ready = false;
|
nickjillings@1620
|
1283 };
|
nickjillings@1620
|
1284 }
|
nickjillings@1620
|
1285 return ready;
|
nickjillings@1620
|
1286 };
|
nickjillings@1620
|
1287
|
nickjillings@1535
|
1288 this.setSynchronousLoop = function() {
|
nickjillings@1535
|
1289 // Pads the signals so they are all exactly the same length
|
nickjillings@1523
|
1290 var length = 0;
|
nickjillings@1523
|
1291 var maxId;
|
nickjillings@1523
|
1292 for (var i=0; i<this.audioObjects.length; i++)
|
nickjillings@1535
|
1293 {
|
nickjillings@1413
|
1294 if (length < this.audioObjects[i].buffer.buffer.length)
|
nickjillings@1535
|
1295 {
|
nickjillings@1413
|
1296 length = this.audioObjects[i].buffer.buffer.length;
|
nickjillings@1523
|
1297 maxId = i;
|
nickjillings@1535
|
1298 }
|
nickjillings@1523
|
1299 }
|
nickjillings@1404
|
1300 // Extract the audio and zero-pad
|
nickjillings@1430
|
1301 for (var i=0; i<this.audioObjects.length; i++)
|
nickjillings@1523
|
1302 {
|
nickjillings@1413
|
1303 var orig = this.audioObjects[i].buffer.buffer;
|
nickjillings@1523
|
1304 var hold = audioContext.createBuffer(orig.numberOfChannels,length,orig.sampleRate);
|
nickjillings@1523
|
1305 for (var c=0; c<orig.numberOfChannels; c++)
|
nickjillings@1535
|
1306 {
|
nickjillings@1523
|
1307 var inData = hold.getChannelData(c);
|
nickjillings@1523
|
1308 var outData = orig.getChannelData(c);
|
nickjillings@1523
|
1309 for (var n=0; n<orig.length; n++)
|
nickjillings@1523
|
1310 {inData[n] = outData[n];}
|
nickjillings@1535
|
1311 }
|
nickjillings@1320
|
1312 hold.playbackGain = orig.playbackGain;
|
nickjillings@1430
|
1313 hold.lufs = orig.lufs;
|
nickjillings@1413
|
1314 this.audioObjects[i].buffer.buffer = hold;
|
nickjillings@1535
|
1315 }
|
nickjillings@1535
|
1316 };
|
nickjillings@1370
|
1317
|
nickjillings@1370
|
1318 this.exportXML = function()
|
nickjillings@1370
|
1319 {
|
nickjillings@1370
|
1320
|
nickjillings@1370
|
1321 };
|
nickjillings@1535
|
1322
|
nickjillings@1682
|
1323 }
|
nickjillings@1682
|
1324
|
nickjillings@1682
|
1325 function audioObject(id) {
|
nickjillings@1682
|
1326 // The main buffer object with common control nodes to the AudioEngine
|
nickjillings@1682
|
1327
|
nickjillings@1582
|
1328 this.specification;
|
nickjillings@1682
|
1329 this.id = id;
|
nickjillings@1682
|
1330 this.state = 0; // 0 - no data, 1 - ready
|
nickjillings@1704
|
1331 this.url = null; // Hold the URL given for the output back to the results.
|
nickjillings@1602
|
1332 this.metric = new metricTracker(this);
|
nickjillings@1324
|
1333 this.storeDOM = null;
|
nickjillings@1682
|
1334
|
nickjillings@1577
|
1335 // Bindings for GUI
|
nickjillings@1583
|
1336 this.interfaceDOM = null;
|
nickjillings@1577
|
1337 this.commentDOM = null;
|
nickjillings@1577
|
1338
|
nickjillings@1682
|
1339 // Create a buffer and external gain control to allow internal patching of effects and volume leveling.
|
nickjillings@1667
|
1340 this.bufferNode = undefined;
|
nickjillings@1682
|
1341 this.outputGain = audioContext.createGain();
|
nickjillings@1682
|
1342
|
nickjillings@1324
|
1343 this.onplayGain = 1.0;
|
nickjillings@1689
|
1344
|
nickjillings@1682
|
1345 // Connect buffer to the audio graph
|
nickjillings@1682
|
1346 this.outputGain.connect(audioEngineContext.outputGain);
|
nickjillings@1682
|
1347
|
nickjillings@1682
|
1348 // the audiobuffer is not designed for multi-start playback
|
nickjillings@1682
|
1349 // When stopeed, the buffer node is deleted and recreated with the stored buffer.
|
nickjillings@1682
|
1350 this.buffer;
|
nickjillings@1434
|
1351
|
nickjillings@1434
|
1352 this.bufferLoaded = function(callee)
|
nickjillings@1434
|
1353 {
|
nickjillings@1434
|
1354 // Called by the associated buffer when it has finished loading, will then 'bind' the buffer to the
|
nickjillings@1434
|
1355 // audioObject and trigger the interfaceDOM.enable() function for user feedback
|
nickjillings@2113
|
1356 if (callee.status == -1) {
|
nickjillings@2113
|
1357 // ERROR
|
nickjillings@2113
|
1358 this.state = -1;
|
nickjillings@2113
|
1359 if (this.interfaceDOM != null) {this.interfaceDOM.error();}
|
nickjillings@2113
|
1360 this.buffer = callee;
|
nickjillings@2113
|
1361 return;
|
nickjillings@2113
|
1362 }
|
nickjillings@1434
|
1363 if (audioEngineContext.loopPlayback){
|
nickjillings@1434
|
1364 // First copy the buffer into this.buffer
|
nickjillings@1434
|
1365 this.buffer = new audioEngineContext.bufferObj();
|
nickjillings@1434
|
1366 this.buffer.url = callee.url;
|
nickjillings@1434
|
1367 this.buffer.buffer = audioContext.createBuffer(callee.buffer.numberOfChannels, callee.buffer.length, callee.buffer.sampleRate);
|
nickjillings@1434
|
1368 for (var c=0; c<callee.buffer.numberOfChannels; c++)
|
nickjillings@1434
|
1369 {
|
nickjillings@1434
|
1370 var src = callee.buffer.getChannelData(c);
|
nickjillings@1434
|
1371 var dst = this.buffer.buffer.getChannelData(c);
|
nickjillings@1434
|
1372 for (var n=0; n<src.length; n++)
|
nickjillings@1434
|
1373 {
|
nickjillings@1434
|
1374 dst[n] = src[n];
|
nickjillings@1434
|
1375 }
|
nickjillings@1434
|
1376 }
|
nickjillings@1434
|
1377 } else {
|
nickjillings@1434
|
1378 this.buffer = callee;
|
nickjillings@1434
|
1379 }
|
nickjillings@1434
|
1380 this.state = 1;
|
nickjillings@1320
|
1381 this.buffer.buffer.playbackGain = callee.buffer.playbackGain;
|
nickjillings@1434
|
1382 this.buffer.buffer.lufs = callee.buffer.lufs;
|
nickjillings@1348
|
1383 var targetLUFS = this.specification.parent.loudness || specification.loudness;
|
nickjillings@1434
|
1384 if (typeof targetLUFS === "number")
|
nickjillings@1434
|
1385 {
|
nickjillings@1320
|
1386 this.buffer.buffer.playbackGain = decibelToLinear(targetLUFS - this.buffer.buffer.lufs);
|
nickjillings@1434
|
1387 } else {
|
nickjillings@1320
|
1388 this.buffer.buffer.playbackGain = 1.0;
|
nickjillings@1434
|
1389 }
|
nickjillings@1434
|
1390 if (this.interfaceDOM != null) {
|
nickjillings@1434
|
1391 this.interfaceDOM.enable();
|
nickjillings@1434
|
1392 }
|
nickjillings@1324
|
1393 this.onplayGain = decibelToLinear(this.specification.gain)*this.buffer.buffer.playbackGain;
|
nickjillings@1324
|
1394 this.storeDOM.setAttribute('playGain',linearToDecibel(this.onplayGain));
|
nickjillings@1318
|
1395 };
|
nickjillings@1325
|
1396
|
nickjillings@1325
|
1397 this.bindInterface = function(interfaceObject)
|
nickjillings@1325
|
1398 {
|
nickjillings@1325
|
1399 this.interfaceDOM = interfaceObject;
|
nickjillings@1325
|
1400 this.metric.initialise(interfaceObject.getValue());
|
nickjillings@1325
|
1401 if (this.state == 1)
|
nickjillings@1325
|
1402 {
|
nickjillings@1325
|
1403 this.interfaceDOM.enable();
|
nickjillings@2113
|
1404 } else if (this.state == -1) {
|
nickjillings@2113
|
1405 // ERROR
|
nickjillings@2113
|
1406 this.interfaceDOM.error();
|
nickjillings@2113
|
1407 return;
|
nickjillings@2113
|
1408 }
|
nickjillings@1338
|
1409 this.storeDOM.setAttribute('presentedId',interfaceObject.getPresentedId());
|
nickjillings@1434
|
1410 };
|
b@1639
|
1411
|
nickjillings@1360
|
1412 this.loopStart = function(setTime) {
|
nickjillings@1360
|
1413 this.outputGain.gain.linearRampToValueAtTime(this.onplayGain,setTime);
|
nickjillings@1637
|
1414 this.metric.startListening(audioEngineContext.timer.getTestTime());
|
nickjillings@1360
|
1415 this.interfaceDOM.startPlayback();
|
nickjillings@1577
|
1416 };
|
nickjillings@1637
|
1417
|
nickjillings@1360
|
1418 this.loopStop = function(setTime) {
|
nickjillings@1637
|
1419 if (this.outputGain.gain.value != 0.0) {
|
nickjillings@1360
|
1420 this.outputGain.gain.linearRampToValueAtTime(0.0,setTime);
|
nickjillings@1637
|
1421 this.metric.stopListening(audioEngineContext.timer.getTestTime());
|
nickjillings@1637
|
1422 }
|
nickjillings@1360
|
1423 this.interfaceDOM.stopPlayback();
|
nickjillings@1577
|
1424 };
|
nickjillings@1637
|
1425
|
nickjillings@1682
|
1426 this.play = function(startTime) {
|
nickjillings@1410
|
1427 if (this.bufferNode == undefined && this.buffer.buffer != undefined) {
|
nickjillings@1565
|
1428 this.bufferNode = audioContext.createBufferSource();
|
nickjillings@1565
|
1429 this.bufferNode.owner = this;
|
nickjillings@1565
|
1430 this.bufferNode.connect(this.outputGain);
|
nickjillings@1410
|
1431 this.bufferNode.buffer = this.buffer.buffer;
|
nickjillings@1565
|
1432 this.bufferNode.loop = audioEngineContext.loopPlayback;
|
nickjillings@1522
|
1433 this.bufferNode.onended = function(event) {
|
nickjillings@1565
|
1434 // Safari does not like using 'this' to reference the calling object!
|
nickjillings@1458
|
1435 //event.currentTarget.owner.metric.stopListening(audioEngineContext.timer.getTestTime(),event.currentTarget.owner.getCurrentPosition());
|
nickjillings@2120
|
1436 if (event.currentTarget != null) {
|
nickjillings@2120
|
1437 event.currentTarget.owner.stop(audioContext.currentTime+1);
|
nickjillings@2120
|
1438 }
|
nickjillings@1565
|
1439 };
|
nickjillings@1565
|
1440 if (this.bufferNode.loop == false) {
|
nickjillings@1565
|
1441 this.metric.startListening(audioEngineContext.timer.getTestTime());
|
nickjillings@1360
|
1442 this.outputGain.gain.setValueAtTime(this.onplayGain,startTime);
|
nickjillings@1360
|
1443 this.interfaceDOM.startPlayback();
|
nickjillings@1360
|
1444 } else {
|
nickjillings@1360
|
1445 this.outputGain.gain.setValueAtTime(0.0,startTime);
|
nickjillings@1360
|
1446 }
|
nickjillings@1565
|
1447 this.bufferNode.start(startTime);
|
nickjillings@2126
|
1448 this.bufferNode.playbackStartTime = audioEngineContext.timer.getTestTime();
|
nickjillings@1617
|
1449 }
|
nickjillings@1697
|
1450 };
|
nickjillings@1682
|
1451
|
nickjillings@1360
|
1452 this.stop = function(stopTime) {
|
nickjillings@1360
|
1453 this.outputGain.gain.cancelScheduledValues(audioContext.currentTime);
|
nickjillings@2002
|
1454 if (this.bufferNode != undefined)
|
nickjillings@2002
|
1455 {
|
nickjillings@1566
|
1456 this.metric.stopListening(audioEngineContext.timer.getTestTime(),this.getCurrentPosition());
|
nickjillings@1360
|
1457 this.bufferNode.stop(stopTime);
|
nickjillings@2002
|
1458 this.bufferNode = undefined;
|
nickjillings@2002
|
1459 }
|
nickjillings@1360
|
1460 this.outputGain.gain.value = 0.0;
|
nickjillings@1360
|
1461 this.interfaceDOM.stopPlayback();
|
nickjillings@1697
|
1462 };
|
nickjillings@2019
|
1463
|
nickjillings@2019
|
1464 this.getCurrentPosition = function() {
|
nickjillings@2019
|
1465 var time = audioEngineContext.timer.getTestTime();
|
nickjillings@2019
|
1466 if (this.bufferNode != undefined) {
|
nickjillings@2138
|
1467 var position = (time - this.bufferNode.playbackStartTime)%this.buffer.buffer.duration;
|
nickjillings@2138
|
1468 if (isNaN(position)){return 0;}
|
nickjillings@2138
|
1469 return position;
|
nickjillings@2019
|
1470 } else {
|
nickjillings@2019
|
1471 return 0;
|
nickjillings@2019
|
1472 }
|
nickjillings@2019
|
1473 };
|
nickjillings@1688
|
1474
|
nickjillings@1583
|
1475 this.exportXMLDOM = function() {
|
nickjillings@1324
|
1476 var file = storage.document.createElement('file');
|
nickjillings@1416
|
1477 file.setAttribute('sampleRate',this.buffer.buffer.sampleRate);
|
nickjillings@1416
|
1478 file.setAttribute('channels',this.buffer.buffer.numberOfChannels);
|
nickjillings@1416
|
1479 file.setAttribute('sampleCount',this.buffer.buffer.length);
|
nickjillings@1416
|
1480 file.setAttribute('duration',this.buffer.buffer.duration);
|
nickjillings@1324
|
1481 this.storeDOM.appendChild(file);
|
nickjillings@1324
|
1482 if (this.specification.type != 'outside-reference') {
|
nickjillings@1413
|
1483 var interfaceXML = this.interfaceDOM.exportXMLDOM(this);
|
nickjillings@1340
|
1484 if (interfaceXML != null)
|
nickjillings@1340
|
1485 {
|
nickjillings@1340
|
1486 if (interfaceXML.length == undefined) {
|
nickjillings@1340
|
1487 this.storeDOM.appendChild(interfaceXML);
|
nickjillings@1340
|
1488 } else {
|
nickjillings@1340
|
1489 for (var i=0; i<interfaceXML.length; i++)
|
nickjillings@1340
|
1490 {
|
nickjillings@1340
|
1491 this.storeDOM.appendChild(interfaceXML[i]);
|
nickjillings@1340
|
1492 }
|
nickjillings@1413
|
1493 }
|
nickjillings@1413
|
1494 }
|
nickjillings@1330
|
1495 if (this.commentDOM != null) {
|
nickjillings@1330
|
1496 this.storeDOM.appendChild(this.commentDOM.exportXMLDOM(this));
|
nickjillings@1529
|
1497 }
|
nickjillings@2050
|
1498 }
|
nickjillings@1324
|
1499 var nodes = this.metric.exportXMLDOM();
|
nickjillings@1324
|
1500 var mroot = this.storeDOM.getElementsByTagName('metric')[0];
|
nickjillings@1324
|
1501 for (var i=0; i<nodes.length; i++)
|
nickjillings@1324
|
1502 {
|
nickjillings@1324
|
1503 mroot.appendChild(nodes[i]);
|
nickjillings@1324
|
1504 }
|
nickjillings@1583
|
1505 };
|
nickjillings@1659
|
1506 }
|
nickjillings@1659
|
1507
|
nickjillings@1659
|
1508 function timer()
|
nickjillings@1659
|
1509 {
|
nickjillings@1659
|
1510 /* Timer object used in audioEngine to keep track of session timings
|
nickjillings@1659
|
1511 * Uses the timer of the web audio API, so sample resolution
|
nickjillings@1659
|
1512 */
|
nickjillings@1659
|
1513 this.testStarted = false;
|
nickjillings@1659
|
1514 this.testStartTime = 0;
|
nickjillings@1659
|
1515 this.testDuration = 0;
|
nickjillings@1659
|
1516 this.minimumTestTime = 0; // No minimum test time
|
nickjillings@1659
|
1517 this.startTest = function()
|
nickjillings@1659
|
1518 {
|
nickjillings@1659
|
1519 if (this.testStarted == false)
|
nickjillings@1659
|
1520 {
|
nickjillings@1659
|
1521 this.testStartTime = audioContext.currentTime;
|
nickjillings@1659
|
1522 this.testStarted = true;
|
nickjillings@1659
|
1523 this.updateTestTime();
|
nickjillings@1662
|
1524 audioEngineContext.metric.initialiseTest();
|
nickjillings@1659
|
1525 }
|
nickjillings@1659
|
1526 };
|
nickjillings@1659
|
1527 this.stopTest = function()
|
nickjillings@1659
|
1528 {
|
nickjillings@1659
|
1529 if (this.testStarted)
|
nickjillings@1659
|
1530 {
|
nickjillings@1659
|
1531 this.testDuration = this.getTestTime();
|
nickjillings@1659
|
1532 this.testStarted = false;
|
nickjillings@1659
|
1533 } else {
|
nickjillings@1659
|
1534 console.log('ERR: Test tried to end before beginning');
|
nickjillings@1659
|
1535 }
|
nickjillings@1659
|
1536 };
|
nickjillings@1659
|
1537 this.updateTestTime = function()
|
nickjillings@1659
|
1538 {
|
nickjillings@1659
|
1539 if (this.testStarted)
|
nickjillings@1659
|
1540 {
|
nickjillings@1659
|
1541 this.testDuration = audioContext.currentTime - this.testStartTime;
|
nickjillings@1659
|
1542 }
|
nickjillings@1659
|
1543 };
|
nickjillings@1659
|
1544 this.getTestTime = function()
|
nickjillings@1659
|
1545 {
|
nickjillings@1659
|
1546 this.updateTestTime();
|
nickjillings@1659
|
1547 return this.testDuration;
|
nickjillings@1659
|
1548 };
|
nickjillings@1659
|
1549 }
|
nickjillings@1659
|
1550
|
nickjillings@1408
|
1551 function sessionMetrics(engine,specification)
|
nickjillings@1659
|
1552 {
|
nickjillings@1659
|
1553 /* Used by audioEngine to link to audioObjects to minimise the timer call timers;
|
nickjillings@1659
|
1554 */
|
nickjillings@1659
|
1555 this.engine = engine;
|
nickjillings@1659
|
1556 this.lastClicked = -1;
|
nickjillings@1659
|
1557 this.data = -1;
|
nickjillings@1620
|
1558 this.reset = function() {
|
nickjillings@1620
|
1559 this.lastClicked = -1;
|
nickjillings@1620
|
1560 this.data = -1;
|
nickjillings@1620
|
1561 };
|
nickjillings@1408
|
1562
|
nickjillings@1408
|
1563 this.enableElementInitialPosition = false;
|
nickjillings@1408
|
1564 this.enableElementListenTracker = false;
|
nickjillings@1408
|
1565 this.enableElementTimer = false;
|
nickjillings@1408
|
1566 this.enableElementTracker = false;
|
nickjillings@1408
|
1567 this.enableFlagListenedTo = false;
|
nickjillings@1408
|
1568 this.enableFlagMoved = false;
|
nickjillings@1408
|
1569 this.enableTestTimer = false;
|
nickjillings@1408
|
1570 // Obtain the metrics enabled
|
nickjillings@1324
|
1571 for (var i=0; i<specification.metrics.enabled.length; i++)
|
nickjillings@1408
|
1572 {
|
nickjillings@1324
|
1573 var node = specification.metrics.enabled[i];
|
nickjillings@1324
|
1574 switch(node)
|
nickjillings@1408
|
1575 {
|
nickjillings@1408
|
1576 case 'testTimer':
|
nickjillings@1408
|
1577 this.enableTestTimer = true;
|
nickjillings@1408
|
1578 break;
|
nickjillings@1408
|
1579 case 'elementTimer':
|
nickjillings@1408
|
1580 this.enableElementTimer = true;
|
nickjillings@1408
|
1581 break;
|
nickjillings@1408
|
1582 case 'elementTracker':
|
nickjillings@1408
|
1583 this.enableElementTracker = true;
|
nickjillings@1408
|
1584 break;
|
nickjillings@1408
|
1585 case 'elementListenTracker':
|
nickjillings@1408
|
1586 this.enableElementListenTracker = true;
|
nickjillings@1408
|
1587 break;
|
nickjillings@1408
|
1588 case 'elementInitialPosition':
|
nickjillings@1408
|
1589 this.enableElementInitialPosition = true;
|
nickjillings@1408
|
1590 break;
|
nickjillings@1408
|
1591 case 'elementFlagListenedTo':
|
nickjillings@1408
|
1592 this.enableFlagListenedTo = true;
|
nickjillings@1408
|
1593 break;
|
nickjillings@1408
|
1594 case 'elementFlagMoved':
|
nickjillings@1408
|
1595 this.enableFlagMoved = true;
|
nickjillings@1408
|
1596 break;
|
nickjillings@1408
|
1597 case 'elementFlagComments':
|
nickjillings@1408
|
1598 this.enableFlagComments = true;
|
nickjillings@1408
|
1599 break;
|
nickjillings@1408
|
1600 }
|
nickjillings@1408
|
1601 }
|
nickjillings@1662
|
1602 this.initialiseTest = function(){};
|
nickjillings@1659
|
1603 }
|
nickjillings@1659
|
1604
|
nickjillings@1602
|
1605 function metricTracker(caller)
|
nickjillings@1659
|
1606 {
|
nickjillings@1659
|
1607 /* Custom object to track and collect metric data
|
nickjillings@1659
|
1608 * Used only inside the audioObjects object.
|
nickjillings@1659
|
1609 */
|
nickjillings@1659
|
1610
|
nickjillings@1659
|
1611 this.listenedTimer = 0;
|
nickjillings@1659
|
1612 this.listenStart = 0;
|
nickjillings@1617
|
1613 this.listenHold = false;
|
nickjillings@1661
|
1614 this.initialPosition = -1;
|
nickjillings@1659
|
1615 this.movementTracker = [];
|
nickjillings@2019
|
1616 this.listenTracker =[];
|
nickjillings@1659
|
1617 this.wasListenedTo = false;
|
nickjillings@1659
|
1618 this.wasMoved = false;
|
nickjillings@1659
|
1619 this.hasComments = false;
|
nickjillings@1602
|
1620 this.parent = caller;
|
nickjillings@1659
|
1621
|
nickjillings@1324
|
1622 this.initialise = function(position)
|
nickjillings@1659
|
1623 {
|
nickjillings@1661
|
1624 if (this.initialPosition == -1) {
|
nickjillings@1661
|
1625 this.initialPosition = position;
|
nickjillings@1325
|
1626 this.moved(0,position);
|
nickjillings@1661
|
1627 }
|
nickjillings@1659
|
1628 };
|
nickjillings@1659
|
1629
|
nickjillings@1659
|
1630 this.moved = function(time,position)
|
nickjillings@1659
|
1631 {
|
nickjillings@1325
|
1632 if (time > 0) {this.wasMoved = true;}
|
nickjillings@1659
|
1633 this.movementTracker[this.movementTracker.length] = [time, position];
|
nickjillings@1659
|
1634 };
|
nickjillings@1659
|
1635
|
nickjillings@1637
|
1636 this.startListening = function(time)
|
nickjillings@1659
|
1637 {
|
nickjillings@1617
|
1638 if (this.listenHold == false)
|
nickjillings@1659
|
1639 {
|
nickjillings@1659
|
1640 this.wasListenedTo = true;
|
nickjillings@1659
|
1641 this.listenStart = time;
|
nickjillings@1617
|
1642 this.listenHold = true;
|
nickjillings@2019
|
1643
|
nickjillings@2019
|
1644 var evnt = document.createElement('event');
|
nickjillings@2019
|
1645 var testTime = document.createElement('testTime');
|
nickjillings@2019
|
1646 testTime.setAttribute('start',time);
|
nickjillings@2019
|
1647 var bufferTime = document.createElement('bufferTime');
|
nickjillings@2019
|
1648 bufferTime.setAttribute('start',this.parent.getCurrentPosition());
|
nickjillings@2019
|
1649 evnt.appendChild(testTime);
|
nickjillings@2019
|
1650 evnt.appendChild(bufferTime);
|
nickjillings@2019
|
1651 this.listenTracker.push(evnt);
|
nickjillings@2019
|
1652
|
nickjillings@1602
|
1653 console.log('slider ' + this.parent.id + ' played (' + time + ')'); // DEBUG/SAFETY: show played slider id
|
nickjillings@1602
|
1654 }
|
nickjillings@1602
|
1655 };
|
nickjillings@1637
|
1656
|
nickjillings@1566
|
1657 this.stopListening = function(time,bufferStopTime)
|
nickjillings@1637
|
1658 {
|
nickjillings@1637
|
1659 if (this.listenHold == true)
|
nickjillings@1637
|
1660 {
|
nickjillings@2019
|
1661 var diff = time - this.listenStart;
|
nickjillings@2019
|
1662 this.listenedTimer += (diff);
|
nickjillings@1659
|
1663 this.listenStart = 0;
|
nickjillings@1617
|
1664 this.listenHold = false;
|
nickjillings@2019
|
1665
|
nickjillings@2019
|
1666 var evnt = this.listenTracker[this.listenTracker.length-1];
|
nickjillings@2019
|
1667 var testTime = evnt.getElementsByTagName('testTime')[0];
|
nickjillings@2019
|
1668 var bufferTime = evnt.getElementsByTagName('bufferTime')[0];
|
nickjillings@2019
|
1669 testTime.setAttribute('stop',time);
|
nickjillings@1566
|
1670 if (bufferStopTime == undefined) {
|
nickjillings@1566
|
1671 bufferTime.setAttribute('stop',this.parent.getCurrentPosition());
|
nickjillings@1566
|
1672 } else {
|
nickjillings@1566
|
1673 bufferTime.setAttribute('stop',bufferStopTime);
|
nickjillings@1566
|
1674 }
|
nickjillings@2019
|
1675 console.log('slider ' + this.parent.id + ' played for (' + diff + ')'); // DEBUG/SAFETY: show played slider id
|
nickjillings@1659
|
1676 }
|
nickjillings@1659
|
1677 };
|
nickjillings@1577
|
1678
|
nickjillings@1577
|
1679 this.exportXMLDOM = function() {
|
nickjillings@1324
|
1680 var storeDOM = [];
|
nickjillings@1577
|
1681 if (audioEngineContext.metric.enableElementTimer) {
|
nickjillings@1324
|
1682 var mElementTimer = storage.document.createElement('metricresult');
|
nickjillings@1577
|
1683 mElementTimer.setAttribute('name','enableElementTimer');
|
nickjillings@1577
|
1684 mElementTimer.textContent = this.listenedTimer;
|
nickjillings@1324
|
1685 storeDOM.push(mElementTimer);
|
nickjillings@1577
|
1686 }
|
nickjillings@1577
|
1687 if (audioEngineContext.metric.enableElementTracker) {
|
nickjillings@1324
|
1688 var elementTrackerFull = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1689 elementTrackerFull.setAttribute('name','elementTrackerFull');
|
nickjillings@1577
|
1690 for (var k=0; k<this.movementTracker.length; k++)
|
nickjillings@1577
|
1691 {
|
nickjillings@2138
|
1692 var timePos = storage.document.createElement('movement');
|
nickjillings@2138
|
1693 timePos.setAttribute("time",this.movementTracker[k][0]);
|
nickjillings@2138
|
1694 timePos.setAttribute("value",this.movementTracker[k][1]);
|
nickjillings@1577
|
1695 elementTrackerFull.appendChild(timePos);
|
nickjillings@1577
|
1696 }
|
nickjillings@1324
|
1697 storeDOM.push(elementTrackerFull);
|
nickjillings@1577
|
1698 }
|
nickjillings@1577
|
1699 if (audioEngineContext.metric.enableElementListenTracker) {
|
nickjillings@1324
|
1700 var elementListenTracker = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1701 elementListenTracker.setAttribute('name','elementListenTracker');
|
nickjillings@1577
|
1702 for (var k=0; k<this.listenTracker.length; k++) {
|
nickjillings@1577
|
1703 elementListenTracker.appendChild(this.listenTracker[k]);
|
nickjillings@1577
|
1704 }
|
nickjillings@1324
|
1705 storeDOM.push(elementListenTracker);
|
nickjillings@1577
|
1706 }
|
nickjillings@1577
|
1707 if (audioEngineContext.metric.enableElementInitialPosition) {
|
nickjillings@1324
|
1708 var elementInitial = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1709 elementInitial.setAttribute('name','elementInitialPosition');
|
nickjillings@1577
|
1710 elementInitial.textContent = this.initialPosition;
|
nickjillings@1324
|
1711 storeDOM.push(elementInitial);
|
nickjillings@1577
|
1712 }
|
nickjillings@1577
|
1713 if (audioEngineContext.metric.enableFlagListenedTo) {
|
nickjillings@1324
|
1714 var flagListenedTo = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1715 flagListenedTo.setAttribute('name','elementFlagListenedTo');
|
nickjillings@1577
|
1716 flagListenedTo.textContent = this.wasListenedTo;
|
nickjillings@1324
|
1717 storeDOM.push(flagListenedTo);
|
nickjillings@1577
|
1718 }
|
nickjillings@1577
|
1719 if (audioEngineContext.metric.enableFlagMoved) {
|
nickjillings@1324
|
1720 var flagMoved = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1721 flagMoved.setAttribute('name','elementFlagMoved');
|
nickjillings@1577
|
1722 flagMoved.textContent = this.wasMoved;
|
nickjillings@1324
|
1723 storeDOM.push(flagMoved);
|
nickjillings@1577
|
1724 }
|
nickjillings@1577
|
1725 if (audioEngineContext.metric.enableFlagComments) {
|
nickjillings@1324
|
1726 var flagComments = storage.document.createElement('metricResult');
|
nickjillings@1577
|
1727 flagComments.setAttribute('name','elementFlagComments');
|
nickjillings@1577
|
1728 if (this.parent.commentDOM == null)
|
nickjillings@1577
|
1729 {flag.textContent = 'false';}
|
nickjillings@1577
|
1730 else if (this.parent.commentDOM.textContent.length == 0)
|
nickjillings@1577
|
1731 {flag.textContent = 'false';}
|
nickjillings@1577
|
1732 else
|
nickjillings@1577
|
1733 {flag.textContet = 'true';}
|
nickjillings@1324
|
1734 storeDOM.push(flagComments);
|
nickjillings@1577
|
1735 }
|
nickjillings@1324
|
1736 return storeDOM;
|
nickjillings@1577
|
1737 };
|
nickjillings@1664
|
1738 }
|
nickjillings@1664
|
1739
|
nickjillings@1664
|
1740 function randomiseOrder(input)
|
nickjillings@1664
|
1741 {
|
nickjillings@1664
|
1742 // This takes an array of information and randomises the order
|
nickjillings@1664
|
1743 var N = input.length;
|
b@2037
|
1744
|
b@2037
|
1745 var inputSequence = []; // For safety purposes: keep track of randomisation
|
b@2037
|
1746 for (var counter = 0; counter < N; ++counter)
|
b@2037
|
1747 inputSequence.push(counter) // Fill array
|
b@2037
|
1748 var inputSequenceClone = inputSequence.slice(0);
|
b@2037
|
1749
|
nickjillings@1664
|
1750 var holdArr = [];
|
b@2037
|
1751 var outputSequence = [];
|
nickjillings@1664
|
1752 for (var n=0; n<N; n++)
|
nickjillings@1664
|
1753 {
|
nickjillings@1664
|
1754 // First pick a random number
|
nickjillings@1664
|
1755 var r = Math.random();
|
nickjillings@1664
|
1756 // Multiply and floor by the number of elements left
|
nickjillings@1664
|
1757 r = Math.floor(r*input.length);
|
nickjillings@1664
|
1758 // Pick out that element and delete from the array
|
nickjillings@1664
|
1759 holdArr.push(input.splice(r,1)[0]);
|
b@2037
|
1760 // Do the same with sequence
|
b@2037
|
1761 outputSequence.push(inputSequence.splice(r,1)[0]);
|
nickjillings@1664
|
1762 }
|
b@2037
|
1763 console.log(inputSequenceClone.toString()); // print original array to console
|
b@2037
|
1764 console.log(outputSequence.toString()); // print randomised array to console
|
nickjillings@1664
|
1765 return holdArr;
|
nickjillings@1631
|
1766 }
|
nickjillings@1631
|
1767
|
nickjillings@1631
|
1768 function returnDateNode()
|
nickjillings@1631
|
1769 {
|
nickjillings@1631
|
1770 // Create an XML Node for the Date and Time a test was conducted
|
nickjillings@1631
|
1771 // Structure is
|
nickjillings@1631
|
1772 // <datetime>
|
nickjillings@1631
|
1773 // <date year="##" month="##" day="##">DD/MM/YY</date>
|
nickjillings@1631
|
1774 // <time hour="##" minute="##" sec="##">HH:MM:SS</time>
|
nickjillings@1631
|
1775 // </datetime>
|
nickjillings@1631
|
1776 var dateTime = new Date();
|
nickjillings@1631
|
1777 var year = document.createAttribute('year');
|
nickjillings@1631
|
1778 var month = document.createAttribute('month');
|
nickjillings@1631
|
1779 var day = document.createAttribute('day');
|
nickjillings@1631
|
1780 var hour = document.createAttribute('hour');
|
nickjillings@1631
|
1781 var minute = document.createAttribute('minute');
|
nickjillings@1631
|
1782 var secs = document.createAttribute('secs');
|
nickjillings@1631
|
1783
|
nickjillings@1631
|
1784 year.nodeValue = dateTime.getFullYear();
|
nickjillings@1631
|
1785 month.nodeValue = dateTime.getMonth()+1;
|
nickjillings@1631
|
1786 day.nodeValue = dateTime.getDate();
|
nickjillings@1631
|
1787 hour.nodeValue = dateTime.getHours();
|
nickjillings@1631
|
1788 minute.nodeValue = dateTime.getMinutes();
|
nickjillings@1631
|
1789 secs.nodeValue = dateTime.getSeconds();
|
nickjillings@1631
|
1790
|
nickjillings@1631
|
1791 var hold = document.createElement("datetime");
|
nickjillings@1631
|
1792 var date = document.createElement("date");
|
nickjillings@1631
|
1793 date.textContent = year.nodeValue+'/'+month.nodeValue+'/'+day.nodeValue;
|
nickjillings@1631
|
1794 var time = document.createElement("time");
|
nickjillings@1631
|
1795 time.textContent = hour.nodeValue+':'+minute.nodeValue+':'+secs.nodeValue;
|
nickjillings@1631
|
1796
|
nickjillings@1631
|
1797 date.setAttributeNode(year);
|
nickjillings@1631
|
1798 date.setAttributeNode(month);
|
nickjillings@1631
|
1799 date.setAttributeNode(day);
|
nickjillings@1631
|
1800 time.setAttributeNode(hour);
|
nickjillings@1631
|
1801 time.setAttributeNode(minute);
|
nickjillings@1631
|
1802 time.setAttributeNode(secs);
|
nickjillings@1631
|
1803
|
nickjillings@1631
|
1804 hold.appendChild(date);
|
nickjillings@1631
|
1805 hold.appendChild(time);
|
nickjillings@1408
|
1806 return hold;
|
nickjillings@1631
|
1807
|
nickjillings@1604
|
1808 }
|
nickjillings@1604
|
1809
|
nickjillings@1580
|
1810 function Specification() {
|
nickjillings@1580
|
1811 // Handles the decoding of the project specification XML into a simple JavaScript Object.
|
nickjillings@1580
|
1812
|
nickjillings@1324
|
1813 this.interface = null;
|
nickjillings@1373
|
1814 this.projectReturn = "null";
|
nickjillings@1324
|
1815 this.randomiseOrder = null;
|
nickjillings@1324
|
1816 this.testPages = null;
|
nickjillings@1324
|
1817 this.pages = [];
|
nickjillings@1324
|
1818 this.metrics = null;
|
nickjillings@1324
|
1819 this.interfaces = null;
|
nickjillings@1324
|
1820 this.loudness = null;
|
nickjillings@1324
|
1821 this.errors = [];
|
nickjillings@1324
|
1822 this.schema = null;
|
nickjillings@1318
|
1823
|
nickjillings@2165
|
1824 this.processAttribute = function(attribute,schema,schemaRoot)
|
nickjillings@1406
|
1825 {
|
nickjillings@1324
|
1826 // attribute is the string returned from getAttribute on the XML
|
nickjillings@1324
|
1827 // schema is the <xs:attribute> node
|
nickjillings@1324
|
1828 if (schema.getAttribute('name') == undefined && schema.getAttribute('ref') != undefined)
|
nickjillings@1406
|
1829 {
|
nickjillings@2165
|
1830 schema = schemaRoot.getAllElementsByName(schema.getAttribute('ref'))[0];
|
nickjillings@1324
|
1831 }
|
nickjillings@1324
|
1832 var defaultOpt = schema.getAttribute('default');
|
nickjillings@1324
|
1833 if (attribute == null) {
|
nickjillings@1324
|
1834 attribute = defaultOpt;
|
nickjillings@1324
|
1835 }
|
nickjillings@1324
|
1836 var dataType = schema.getAttribute('type');
|
nickjillings@1324
|
1837 if (typeof dataType == "string") { dataType = dataType.substr(3);}
|
nickjillings@1324
|
1838 else {dataType = "string";}
|
nickjillings@1324
|
1839 if (attribute == null)
|
nickjillings@1324
|
1840 {
|
nickjillings@1324
|
1841 return attribute;
|
nickjillings@1324
|
1842 }
|
nickjillings@1324
|
1843 switch(dataType)
|
nickjillings@1324
|
1844 {
|
nickjillings@1324
|
1845 case "boolean":
|
nickjillings@1324
|
1846 if (attribute == 'true'){attribute = true;}else{attribute=false;}
|
nickjillings@1324
|
1847 break;
|
nickjillings@1324
|
1848 case "negativeInteger":
|
nickjillings@1324
|
1849 case "positiveInteger":
|
nickjillings@1324
|
1850 case "nonNegativeInteger":
|
nickjillings@1324
|
1851 case "nonPositiveInteger":
|
nickjillings@1324
|
1852 case "integer":
|
nickjillings@1324
|
1853 case "decimal":
|
nickjillings@1324
|
1854 case "short":
|
nickjillings@1324
|
1855 attribute = Number(attribute);
|
nickjillings@1324
|
1856 break;
|
nickjillings@1324
|
1857 case "string":
|
nickjillings@1324
|
1858 default:
|
nickjillings@1324
|
1859 attribute = String(attribute);
|
nickjillings@1324
|
1860 break;
|
nickjillings@1324
|
1861 }
|
nickjillings@1324
|
1862 return attribute;
|
nickjillings@1406
|
1863 };
|
nickjillings@1411
|
1864
|
nickjillings@1406
|
1865 this.decode = function(projectXML) {
|
nickjillings@1324
|
1866 this.errors = [];
|
nickjillings@1580
|
1867 // projectXML - DOM Parsed document
|
nickjillings@2052
|
1868 this.projectXML = projectXML.childNodes[0];
|
nickjillings@1580
|
1869 var setupNode = projectXML.getElementsByTagName('setup')[0];
|
nickjillings@1348
|
1870 var schemaSetup = this.schema.getAllElementsByName('setup')[0];
|
nickjillings@1324
|
1871 // First decode the attributes
|
nickjillings@1348
|
1872 var attributes = schemaSetup.getAllElementsByTagName('xs:attribute');
|
nickjillings@1324
|
1873 for (var i in attributes)
|
nickjillings@1520
|
1874 {
|
nickjillings@1324
|
1875 if (isNaN(Number(i)) == true){break;}
|
nickjillings@2165
|
1876 var attributeName = attributes[i].getAttribute('name') || attributes[i].getAttribute('ref');
|
nickjillings@1324
|
1877 var projectAttr = setupNode.getAttribute(attributeName);
|
nickjillings@2165
|
1878 projectAttr = this.processAttribute(projectAttr,attributes[i],this.schema);
|
nickjillings@1324
|
1879 switch(typeof projectAttr)
|
nickjillings@1432
|
1880 {
|
nickjillings@1324
|
1881 case "number":
|
nickjillings@1324
|
1882 case "boolean":
|
nickjillings@1324
|
1883 eval('this.'+attributeName+' = '+projectAttr);
|
nickjillings@1324
|
1884 break;
|
nickjillings@1324
|
1885 case "string":
|
nickjillings@1324
|
1886 eval('this.'+attributeName+' = "'+projectAttr+'"');
|
nickjillings@1324
|
1887 break;
|
nickjillings@1432
|
1888 }
|
nickjillings@1324
|
1889
|
nickjillings@1406
|
1890 }
|
nickjillings@1406
|
1891
|
nickjillings@1370
|
1892 this.metrics = new this.metricNode();
|
nickjillings@1580
|
1893
|
nickjillings@1324
|
1894 this.metrics.decode(this,setupNode.getElementsByTagName('metric')[0]);
|
nickjillings@1324
|
1895
|
nickjillings@1324
|
1896 // Now process the survey node options
|
nickjillings@1324
|
1897 var survey = setupNode.getElementsByTagName('survey');
|
nickjillings@1324
|
1898 for (var i in survey) {
|
nickjillings@1324
|
1899 if (isNaN(Number(i)) == true){break;}
|
nickjillings@1324
|
1900 var location = survey[i].getAttribute('location');
|
nickjillings@1324
|
1901 if (location == 'pre' || location == 'before')
|
nickjillings@1324
|
1902 {
|
nickjillings@1324
|
1903 if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");}
|
nickjillings@1324
|
1904 else {
|
nickjillings@1324
|
1905 this.preTest = new this.surveyNode();
|
nickjillings@1370
|
1906 this.preTest.decode(this,survey[i]);
|
nickjillings@1324
|
1907 }
|
nickjillings@1324
|
1908 } else if (location == 'post' || location == 'after') {
|
nickjillings@1324
|
1909 if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");}
|
nickjillings@1324
|
1910 else {
|
nickjillings@1324
|
1911 this.postTest = new this.surveyNode();
|
nickjillings@1370
|
1912 this.postTest.decode(this,survey[i]);
|
nickjillings@1324
|
1913 }
|
nickjillings@1580
|
1914 }
|
nickjillings@1580
|
1915 }
|
nickjillings@1580
|
1916
|
nickjillings@1324
|
1917 var interfaceNode = setupNode.getElementsByTagName('interface');
|
nickjillings@1324
|
1918 if (interfaceNode.length > 1)
|
nickjillings@1324
|
1919 {
|
nickjillings@1324
|
1920 this.errors.push("Only one <interface> node in the <setup> node allowed! Others except first ingnored!");
|
nickjillings@1324
|
1921 }
|
nickjillings@1324
|
1922 this.interfaces = new this.interfaceNode();
|
nickjillings@1324
|
1923 if (interfaceNode.length != 0)
|
nickjillings@1324
|
1924 {
|
nickjillings@1324
|
1925 interfaceNode = interfaceNode[0];
|
nickjillings@1348
|
1926 this.interfaces.decode(this,interfaceNode,this.schema.getAllElementsByName('interface')[1]);
|
nickjillings@1556
|
1927 }
|
nickjillings@1556
|
1928
|
nickjillings@1324
|
1929 // Page tags
|
nickjillings@1324
|
1930 var pageTags = projectXML.getElementsByTagName('page');
|
nickjillings@1348
|
1931 var pageSchema = this.schema.getAllElementsByName('page')[0];
|
nickjillings@1324
|
1932 for (var i=0; i<pageTags.length; i++)
|
nickjillings@1520
|
1933 {
|
nickjillings@1324
|
1934 var node = new this.page();
|
nickjillings@1324
|
1935 node.decode(this,pageTags[i],pageSchema);
|
nickjillings@1324
|
1936 this.pages.push(node);
|
nickjillings@1520
|
1937 }
|
nickjillings@1580
|
1938 };
|
nickjillings@1580
|
1939
|
nickjillings@1406
|
1940 this.encode = function()
|
nickjillings@1406
|
1941 {
|
nickjillings@1372
|
1942 var RootDocument = document.implementation.createDocument(null,"waet");
|
nickjillings@1372
|
1943 var root = RootDocument.children[0];
|
nickjillings@1372
|
1944 root.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
|
nickjillings@1372
|
1945 root.setAttribute("xsi:noNamespaceSchemaLocation","test-schema.xsd");
|
nickjillings@1324
|
1946 // Build setup node
|
nickjillings@1372
|
1947 var setup = RootDocument.createElement("setup");
|
nickjillings@1372
|
1948 var schemaSetup = this.schema.getAllElementsByName('setup')[0];
|
nickjillings@1372
|
1949 // First decode the attributes
|
nickjillings@1372
|
1950 var attributes = schemaSetup.getAllElementsByTagName('xs:attribute');
|
nickjillings@1372
|
1951 for (var i=0; i<attributes.length; i++)
|
nickjillings@1372
|
1952 {
|
nickjillings@1372
|
1953 var name = attributes[i].getAttribute("name");
|
nickjillings@1372
|
1954 if (name == undefined) {
|
nickjillings@1372
|
1955 name = attributes[i].getAttribute("ref");
|
nickjillings@1372
|
1956 }
|
nickjillings@1372
|
1957 if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required")
|
nickjillings@1372
|
1958 {
|
nickjillings@1372
|
1959 eval("setup.setAttribute('"+name+"',this."+name+")");
|
nickjillings@1372
|
1960 }
|
nickjillings@1372
|
1961 }
|
nickjillings@1372
|
1962 root.appendChild(setup);
|
nickjillings@1372
|
1963 // Survey node
|
nickjillings@1372
|
1964 setup.appendChild(this.preTest.encode(RootDocument));
|
nickjillings@1372
|
1965 setup.appendChild(this.postTest.encode(RootDocument));
|
nickjillings@1372
|
1966 setup.appendChild(this.metrics.encode(RootDocument));
|
nickjillings@1372
|
1967 setup.appendChild(this.interfaces.encode(RootDocument));
|
nickjillings@1372
|
1968 for (var page of this.pages)
|
nickjillings@1372
|
1969 {
|
nickjillings@1372
|
1970 root.appendChild(page.encode(RootDocument));
|
nickjillings@1372
|
1971 }
|
nickjillings@1372
|
1972 return RootDocument;
|
nickjillings@1406
|
1973 };
|
nickjillings@1406
|
1974
|
nickjillings@1324
|
1975 this.surveyNode = function() {
|
nickjillings@1324
|
1976 this.location = null;
|
nickjillings@1580
|
1977 this.options = [];
|
nickjillings@2165
|
1978 this.parent = null;
|
nickjillings@1370
|
1979 this.schema = specification.schema.getAllElementsByName('survey')[0];
|
nickjillings@1580
|
1980
|
nickjillings@1406
|
1981 this.OptionNode = function() {
|
nickjillings@1406
|
1982 this.type = undefined;
|
nickjillings@1370
|
1983 this.schema = specification.schema.getAllElementsByName('surveyentry')[0];
|
nickjillings@1406
|
1984 this.id = undefined;
|
nickjillings@2156
|
1985 this.name = undefined;
|
nickjillings@1406
|
1986 this.mandatory = undefined;
|
nickjillings@1406
|
1987 this.statement = undefined;
|
nickjillings@1406
|
1988 this.boxsize = undefined;
|
nickjillings@1406
|
1989 this.options = [];
|
nickjillings@1406
|
1990 this.min = undefined;
|
nickjillings@1406
|
1991 this.max = undefined;
|
nickjillings@1406
|
1992 this.step = undefined;
|
nickjillings@1406
|
1993
|
nickjillings@1370
|
1994 this.decode = function(parent,child)
|
nickjillings@1406
|
1995 {
|
nickjillings@1370
|
1996 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1324
|
1997 for (var i in attributeMap){
|
nickjillings@1324
|
1998 if(isNaN(Number(i)) == true){break;}
|
nickjillings@1324
|
1999 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
|
nickjillings@1324
|
2000 var projectAttr = child.getAttribute(attributeName);
|
nickjillings@2165
|
2001 projectAttr = parent.processAttribute(projectAttr,attributeMap[i],parent.schema);
|
nickjillings@1324
|
2002 switch(typeof projectAttr)
|
nickjillings@1324
|
2003 {
|
nickjillings@1324
|
2004 case "number":
|
nickjillings@1324
|
2005 case "boolean":
|
nickjillings@1324
|
2006 eval('this.'+attributeName+' = '+projectAttr);
|
nickjillings@1324
|
2007 break;
|
nickjillings@1324
|
2008 case "string":
|
nickjillings@1324
|
2009 eval('this.'+attributeName+' = "'+projectAttr+'"');
|
nickjillings@1324
|
2010 break;
|
nickjillings@1406
|
2011 }
|
nickjillings@1324
|
2012 }
|
nickjillings@1324
|
2013 this.statement = child.getElementsByTagName('statement')[0].textContent;
|
nickjillings@1324
|
2014 if (this.type == "checkbox" || this.type == "radio") {
|
nickjillings@1324
|
2015 var children = child.getElementsByTagName('option');
|
nickjillings@1324
|
2016 if (children.length == null) {
|
nickjillings@1406
|
2017 console.log('Malformed' +child.nodeName+ 'entry');
|
nickjillings@1406
|
2018 this.statement = 'Malformed' +child.nodeName+ 'entry';
|
nickjillings@1406
|
2019 this.type = 'statement';
|
nickjillings@1406
|
2020 } else {
|
nickjillings@1406
|
2021 this.options = [];
|
nickjillings@1324
|
2022 for (var i in children)
|
nickjillings@1324
|
2023 {
|
nickjillings@1324
|
2024 if (isNaN(Number(i))==true){break;}
|
nickjillings@1324
|
2025 this.options.push({
|
nickjillings@1324
|
2026 name: children[i].getAttribute('name'),
|
nickjillings@1324
|
2027 text: children[i].textContent
|
nickjillings@1324
|
2028 });
|
nickjillings@1406
|
2029 }
|
nickjillings@1406
|
2030 }
|
nickjillings@2030
|
2031 }
|
nickjillings@1406
|
2032 };
|
nickjillings@1406
|
2033
|
nickjillings@1372
|
2034 this.exportXML = function(doc)
|
nickjillings@1406
|
2035 {
|
nickjillings@2111
|
2036 var node = doc.createElement('surveyentry');
|
nickjillings@1324
|
2037 node.setAttribute('type',this.type);
|
nickjillings@1372
|
2038 var statement = doc.createElement('statement');
|
nickjillings@1324
|
2039 statement.textContent = this.statement;
|
nickjillings@1324
|
2040 node.appendChild(statement);
|
nickjillings@2162
|
2041 node.id = this.id;
|
nickjillings@2162
|
2042 if (this.name != undefined) { node.setAttribute("name",this.name);}
|
nickjillings@2162
|
2043 if (this.mandatory != undefined) { node.setAttribute("mandatory",this.mandatory);}
|
nickjillings@2162
|
2044 node.id = this.id;
|
nickjillings@2162
|
2045 if (this.name != undefined) {node.setAttribute("name",this.name);}
|
nickjillings@2162
|
2046 switch(this.type)
|
nickjillings@2162
|
2047 {
|
nickjillings@2156
|
2048 case "checkbox":
|
nickjillings@2156
|
2049 case "radio":
|
nickjillings@2156
|
2050 for (var i=0; i<this.options.length; i++)
|
nickjillings@2156
|
2051 {
|
nickjillings@2156
|
2052 var option = this.options[i];
|
nickjillings@2156
|
2053 var optionNode = doc.createElement("option");
|
nickjillings@2156
|
2054 optionNode.setAttribute("name",option.name);
|
nickjillings@2156
|
2055 optionNode.textContent = option.text;
|
nickjillings@2156
|
2056 node.appendChild(optionNode);
|
nickjillings@2156
|
2057 }
|
nickjillings@2162
|
2058 case "number":
|
nickjillings@2162
|
2059 if (this.min != undefined) {node.setAttribute("min", this.min);}
|
nickjillings@2162
|
2060 if (this.max != undefined) {node.setAttribute("max", this.max);}
|
nickjillings@2162
|
2061 case "question":
|
nickjillings@2162
|
2062 if (this.boxsize != undefined) {node.setAttribute("boxsize",this.boxsize);}
|
nickjillings@2162
|
2063 if (this.mandatory != undefined) {node.setAttribute("mandatory",this.mandatory);}
|
nickjillings@2162
|
2064 default:
|
nickjillings@2156
|
2065 break;
|
nickjillings@2156
|
2066 }
|
nickjillings@1406
|
2067 return node;
|
nickjillings@1406
|
2068 };
|
nickjillings@1406
|
2069 };
|
nickjillings@1370
|
2070 this.decode = function(parent,xml) {
|
nickjillings@2165
|
2071 this.parent = parent;
|
nickjillings@1324
|
2072 this.location = xml.getAttribute('location');
|
nickjillings@1324
|
2073 if (this.location == 'before'){this.location = 'pre';}
|
nickjillings@1324
|
2074 else if (this.location == 'after'){this.location = 'post';}
|
nickjillings@1324
|
2075 for (var i in xml.children)
|
nickjillings@1324
|
2076 {
|
nickjillings@1324
|
2077 if(isNaN(Number(i))==true){break;}
|
nickjillings@1406
|
2078 var node = new this.OptionNode();
|
nickjillings@1370
|
2079 node.decode(parent,xml.children[i]);
|
nickjillings@1406
|
2080 this.options.push(node);
|
nickjillings@1324
|
2081 }
|
nickjillings@1324
|
2082 };
|
nickjillings@1372
|
2083 this.encode = function(doc) {
|
nickjillings@1372
|
2084 var node = doc.createElement('survey');
|
nickjillings@1324
|
2085 node.setAttribute('location',this.location);
|
nickjillings@1324
|
2086 for (var i=0; i<this.options.length; i++)
|
nickjillings@1324
|
2087 {
|
nickjillings@1372
|
2088 node.appendChild(this.options[i].exportXML(doc));
|
nickjillings@1324
|
2089 }
|
nickjillings@1324
|
2090 return node;
|
nickjillings@1324
|
2091 };
|
nickjillings@1324
|
2092 };
|
nickjillings@1324
|
2093
|
nickjillings@1324
|
2094 this.interfaceNode = function()
|
nickjillings@1324
|
2095 {
|
nickjillings@1324
|
2096 this.title = null;
|
nickjillings@1324
|
2097 this.name = null;
|
nickjillings@1324
|
2098 this.options = [];
|
nickjillings@1324
|
2099 this.scales = [];
|
nickjillings@1370
|
2100 this.schema = specification.schema.getAllElementsByName('interface')[1];
|
nickjillings@1324
|
2101
|
nickjillings@1370
|
2102 this.decode = function(parent,xml) {
|
nickjillings@1324
|
2103 this.name = xml.getAttribute('name');
|
nickjillings@1324
|
2104 var titleNode = xml.getElementsByTagName('title');
|
nickjillings@1324
|
2105 if (titleNode.length == 1)
|
nickjillings@1324
|
2106 {
|
nickjillings@1324
|
2107 this.title = titleNode[0].textContent;
|
nickjillings@1324
|
2108 }
|
nickjillings@1324
|
2109 var interfaceOptionNodes = xml.getElementsByTagName('interfaceoption');
|
nickjillings@1324
|
2110 // Extract interfaceoption node schema
|
nickjillings@1370
|
2111 var interfaceOptionNodeSchema = this.schema.getAllElementsByName('interfaceoption')[0];
|
nickjillings@1348
|
2112 var attributeMap = interfaceOptionNodeSchema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1324
|
2113 for (var i=0; i<interfaceOptionNodes.length; i++)
|
nickjillings@1324
|
2114 {
|
nickjillings@1324
|
2115 var ioNode = interfaceOptionNodes[i];
|
nickjillings@1324
|
2116 var option = {};
|
nickjillings@1324
|
2117 for (var j=0; j<attributeMap.length; j++)
|
nickjillings@1324
|
2118 {
|
nickjillings@1324
|
2119 var attributeName = attributeMap[j].getAttribute('name') || attributeMap[j].getAttribute('ref');
|
nickjillings@1324
|
2120 var projectAttr = ioNode.getAttribute(attributeName);
|
nickjillings@2165
|
2121 if(parent.processAttribute) {
|
nickjillings@2165
|
2122 parent.processAttribute(projectAttr, attributeMap[j], parent.schema)
|
nickjillings@2165
|
2123 } else {
|
nickjillings@2165
|
2124 parent.parent.processAttribute(projectAttr, attributeMap[j], parent.parent.schema)
|
nickjillings@2165
|
2125 }
|
nickjillings@1324
|
2126 switch(typeof projectAttr)
|
nickjillings@1324
|
2127 {
|
nickjillings@1324
|
2128 case "number":
|
nickjillings@1324
|
2129 case "boolean":
|
nickjillings@1324
|
2130 eval('option.'+attributeName+' = '+projectAttr);
|
nickjillings@1324
|
2131 break;
|
nickjillings@1324
|
2132 case "string":
|
nickjillings@1324
|
2133 eval('option.'+attributeName+' = "'+projectAttr+'"');
|
nickjillings@1324
|
2134 break;
|
nickjillings@1324
|
2135 }
|
nickjillings@1324
|
2136 }
|
nickjillings@1324
|
2137 this.options.push(option);
|
nickjillings@1324
|
2138 }
|
nickjillings@1324
|
2139
|
nickjillings@1324
|
2140 // Now the scales nodes
|
nickjillings@1324
|
2141 var scaleParent = xml.getElementsByTagName('scales');
|
nickjillings@1324
|
2142 if (scaleParent.length == 1) {
|
nickjillings@1324
|
2143 scaleParent = scaleParent[0];
|
nickjillings@1324
|
2144 for (var i=0; i<scaleParent.children.length; i++) {
|
nickjillings@1324
|
2145 var child = scaleParent.children[i];
|
nickjillings@1324
|
2146 this.scales.push({
|
nickjillings@1324
|
2147 text: child.textContent,
|
nickjillings@1324
|
2148 position: Number(child.getAttribute('position'))
|
nickjillings@1324
|
2149 });
|
nickjillings@1406
|
2150 }
|
nickjillings@1580
|
2151 }
|
nickjillings@1580
|
2152 };
|
nickjillings@1324
|
2153
|
nickjillings@1372
|
2154 this.encode = function(doc) {
|
nickjillings@1372
|
2155 var node = doc.createElement("interface");
|
nickjillings@1372
|
2156 if (typeof name == "string")
|
nickjillings@1372
|
2157 node.setAttribute("name",this.name);
|
nickjillings@1372
|
2158 for (var option of this.options)
|
nickjillings@1372
|
2159 {
|
nickjillings@1372
|
2160 var child = doc.createElement("interfaceoption");
|
nickjillings@1372
|
2161 child.setAttribute("type",option.type);
|
nickjillings@1372
|
2162 child.setAttribute("name",option.name);
|
nickjillings@1372
|
2163 node.appendChild(child);
|
nickjillings@1372
|
2164 }
|
nickjillings@1372
|
2165 if (this.scales.length != 0) {
|
nickjillings@1372
|
2166 var scales = doc.createElement("scales");
|
nickjillings@1372
|
2167 for (var scale of this.scales)
|
nickjillings@1372
|
2168 {
|
nickjillings@1372
|
2169 var child = doc.createElement("scalelabel");
|
nickjillings@1372
|
2170 child.setAttribute("position",scale.position);
|
nickjillings@1372
|
2171 child.textContent = scale.text;
|
nickjillings@1372
|
2172 scales.appendChild(child);
|
nickjillings@1372
|
2173 }
|
nickjillings@1372
|
2174 node.appendChild(scales);
|
nickjillings@1372
|
2175 }
|
nickjillings@1372
|
2176 return node;
|
nickjillings@1324
|
2177 };
|
nickjillings@1580
|
2178 };
|
nickjillings@1580
|
2179
|
nickjillings@1370
|
2180 this.metricNode = function() {
|
nickjillings@1370
|
2181 this.enabled = [];
|
nickjillings@1370
|
2182 this.decode = function(parent, xml) {
|
nickjillings@1370
|
2183 var children = xml.getElementsByTagName('metricenable');
|
nickjillings@1370
|
2184 for (var i in children) {
|
nickjillings@1370
|
2185 if (isNaN(Number(i)) == true){break;}
|
nickjillings@1370
|
2186 this.enabled.push(children[i].textContent);
|
nickjillings@1370
|
2187 }
|
nickjillings@1370
|
2188 }
|
nickjillings@1372
|
2189 this.encode = function(doc) {
|
nickjillings@1372
|
2190 var node = doc.createElement('metric');
|
nickjillings@1370
|
2191 for (var i in this.enabled)
|
nickjillings@1370
|
2192 {
|
nickjillings@1370
|
2193 if (isNaN(Number(i)) == true){break;}
|
nickjillings@1372
|
2194 var child = doc.createElement('metricenable');
|
nickjillings@1370
|
2195 child.textContent = this.enabled[i];
|
nickjillings@1370
|
2196 node.appendChild(child);
|
nickjillings@1370
|
2197 }
|
nickjillings@1370
|
2198 return node;
|
nickjillings@1370
|
2199 }
|
nickjillings@1370
|
2200 }
|
nickjillings@1370
|
2201
|
nickjillings@1324
|
2202 this.page = function() {
|
nickjillings@1406
|
2203 this.presentedId = undefined;
|
nickjillings@1406
|
2204 this.id = undefined;
|
nickjillings@1406
|
2205 this.hostURL = undefined;
|
nickjillings@1406
|
2206 this.randomiseOrder = undefined;
|
nickjillings@1406
|
2207 this.loop = undefined;
|
nickjillings@1324
|
2208 this.showElementComments = undefined;
|
nickjillings@1406
|
2209 this.outsideReference = null;
|
nickjillings@1432
|
2210 this.loudness = null;
|
nickjillings@1295
|
2211 this.label = null;
|
nickjillings@1324
|
2212 this.preTest = null;
|
nickjillings@1324
|
2213 this.postTest = null;
|
nickjillings@1406
|
2214 this.interfaces = [];
|
nickjillings@1406
|
2215 this.commentBoxPrefix = "Comment on track";
|
nickjillings@1406
|
2216 this.audioElements = [];
|
nickjillings@1406
|
2217 this.commentQuestions = [];
|
nickjillings@1370
|
2218 this.schema = specification.schema.getAllElementsByName("page")[0];
|
nickjillings@2165
|
2219 this.parent = null;
|
nickjillings@1406
|
2220
|
nickjillings@1406
|
2221 this.decode = function(parent,xml)
|
nickjillings@1406
|
2222 {
|
nickjillings@2165
|
2223 this.parent = parent;
|
nickjillings@1348
|
2224 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1324
|
2225 for (var i=0; i<attributeMap.length; i++)
|
nickjillings@1432
|
2226 {
|
nickjillings@1324
|
2227 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
|
nickjillings@1324
|
2228 var projectAttr = xml.getAttribute(attributeName);
|
nickjillings@2165
|
2229 projectAttr = parent.processAttribute(projectAttr,attributeMap[i],parent.schema);
|
nickjillings@1324
|
2230 switch(typeof projectAttr)
|
nickjillings@1395
|
2231 {
|
nickjillings@1324
|
2232 case "number":
|
nickjillings@1324
|
2233 case "boolean":
|
nickjillings@1324
|
2234 eval('this.'+attributeName+' = '+projectAttr);
|
nickjillings@1324
|
2235 break;
|
nickjillings@1324
|
2236 case "string":
|
nickjillings@1324
|
2237 eval('this.'+attributeName+' = "'+projectAttr+'"');
|
nickjillings@1324
|
2238 break;
|
nickjillings@1406
|
2239 }
|
nickjillings@1406
|
2240 }
|
nickjillings@1406
|
2241
|
nickjillings@1324
|
2242 // Get the Comment Box Prefix
|
nickjillings@1324
|
2243 var CBP = xml.getElementsByTagName('commentboxprefix');
|
nickjillings@1324
|
2244 if (CBP.length != 0) {
|
nickjillings@1324
|
2245 this.commentBoxPrefix = CBP[0].textContent;
|
nickjillings@1441
|
2246 }
|
nickjillings@1441
|
2247
|
nickjillings@1324
|
2248 // Now decode the interfaces
|
nickjillings@1324
|
2249 var interfaceNode = xml.getElementsByTagName('interface');
|
nickjillings@1324
|
2250 for (var i=0; i<interfaceNode.length; i++)
|
nickjillings@1324
|
2251 {
|
nickjillings@1324
|
2252 var node = new parent.interfaceNode();
|
nickjillings@1348
|
2253 node.decode(this,interfaceNode[i],parent.schema.getAllElementsByName('interface')[1]);
|
nickjillings@1324
|
2254 this.interfaces.push(node);
|
nickjillings@1324
|
2255 }
|
nickjillings@1411
|
2256
|
nickjillings@1324
|
2257 // Now process the survey node options
|
nickjillings@1324
|
2258 var survey = xml.getElementsByTagName('survey');
|
nickjillings@1348
|
2259 var surveySchema = parent.schema.getAllElementsByName('survey')[0];
|
nickjillings@1324
|
2260 for (var i in survey) {
|
nickjillings@1324
|
2261 if (isNaN(Number(i)) == true){break;}
|
nickjillings@1324
|
2262 var location = survey[i].getAttribute('location');
|
nickjillings@1324
|
2263 if (location == 'pre' || location == 'before')
|
nickjillings@1324
|
2264 {
|
nickjillings@1324
|
2265 if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");}
|
nickjillings@1324
|
2266 else {
|
nickjillings@1324
|
2267 this.preTest = new parent.surveyNode();
|
nickjillings@1324
|
2268 this.preTest.decode(parent,survey[i],surveySchema);
|
nickjillings@1324
|
2269 }
|
nickjillings@1324
|
2270 } else if (location == 'post' || location == 'after') {
|
nickjillings@1324
|
2271 if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");}
|
nickjillings@1324
|
2272 else {
|
nickjillings@1324
|
2273 this.postTest = new parent.surveyNode();
|
nickjillings@1324
|
2274 this.postTest.decode(parent,survey[i],surveySchema);
|
nickjillings@1324
|
2275 }
|
nickjillings@1324
|
2276 }
|
nickjillings@1324
|
2277 }
|
nickjillings@1324
|
2278
|
nickjillings@1324
|
2279 // Now process the audioelement tags
|
nickjillings@1324
|
2280 var audioElements = xml.getElementsByTagName('audioelement');
|
nickjillings@1324
|
2281 for (var i=0; i<audioElements.length; i++)
|
nickjillings@1324
|
2282 {
|
nickjillings@1324
|
2283 var node = new this.audioElementNode();
|
nickjillings@1370
|
2284 node.decode(this,audioElements[i]);
|
nickjillings@1324
|
2285 this.audioElements.push(node);
|
nickjillings@1324
|
2286 }
|
nickjillings@1324
|
2287
|
nickjillings@1324
|
2288 // Now decode the commentquestions
|
nickjillings@1324
|
2289 var commentQuestions = xml.getElementsByTagName('commentquestion');
|
nickjillings@1324
|
2290 for (var i=0; i<commentQuestions.length; i++)
|
nickjillings@1324
|
2291 {
|
nickjillings@1406
|
2292 var node = new this.commentQuestionNode();
|
nickjillings@1370
|
2293 node.decode(parent,commentQuestions[i]);
|
nickjillings@1406
|
2294 this.commentQuestions.push(node);
|
nickjillings@1580
|
2295 }
|
nickjillings@1580
|
2296 };
|
nickjillings@1580
|
2297
|
nickjillings@1406
|
2298 this.encode = function(root)
|
nickjillings@1406
|
2299 {
|
nickjillings@1372
|
2300 var AHNode = root.createElement("page");
|
nickjillings@1372
|
2301 // First decode the attributes
|
nickjillings@1372
|
2302 var attributes = this.schema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1372
|
2303 for (var i=0; i<attributes.length; i++)
|
nickjillings@1372
|
2304 {
|
nickjillings@1372
|
2305 var name = attributes[i].getAttribute("name");
|
nickjillings@1372
|
2306 if (name == undefined) {
|
nickjillings@1372
|
2307 name = attributes[i].getAttribute("ref");
|
nickjillings@1372
|
2308 }
|
nickjillings@1372
|
2309 if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required")
|
nickjillings@1372
|
2310 {
|
nickjillings@1372
|
2311 eval("AHNode.setAttribute('"+name+"',this."+name+")");
|
nickjillings@1372
|
2312 }
|
nickjillings@1372
|
2313 }
|
nickjillings@1432
|
2314 if(this.loudness != null) {AHNode.setAttribute("loudness",this.loudness);}
|
nickjillings@1372
|
2315 // <commentboxprefix>
|
nickjillings@1372
|
2316 var commentboxprefix = root.createElement("commentboxprefix");
|
nickjillings@1372
|
2317 commentboxprefix.textContent = this.commentBoxPrefix;
|
nickjillings@1372
|
2318 AHNode.appendChild(commentboxprefix);
|
nickjillings@1372
|
2319
|
nickjillings@1406
|
2320 for (var i=0; i<this.interfaces.length; i++)
|
nickjillings@1404
|
2321 {
|
nickjillings@1406
|
2322 AHNode.appendChild(this.interfaces[i].encode(root));
|
nickjillings@1406
|
2323 }
|
nickjillings@1558
|
2324
|
nickjillings@1406
|
2325 for (var i=0; i<this.audioElements.length; i++) {
|
nickjillings@1406
|
2326 AHNode.appendChild(this.audioElements[i].encode(root));
|
nickjillings@1406
|
2327 }
|
nickjillings@1406
|
2328 // Create <CommentQuestion>
|
nickjillings@1406
|
2329 for (var i=0; i<this.commentQuestions.length; i++)
|
nickjillings@1455
|
2330 {
|
nickjillings@1372
|
2331 AHNode.appendChild(this.commentQuestions[i].encode(root));
|
nickjillings@1406
|
2332 }
|
nickjillings@1406
|
2333
|
nickjillings@1372
|
2334 AHNode.appendChild(this.preTest.encode(root));
|
nickjillings@1372
|
2335 AHNode.appendChild(this.postTest.encode(root));
|
nickjillings@1406
|
2336 return AHNode;
|
nickjillings@1406
|
2337 };
|
nickjillings@1406
|
2338
|
nickjillings@1324
|
2339 this.commentQuestionNode = function() {
|
nickjillings@1324
|
2340 this.id = null;
|
nickjillings@2156
|
2341 this.name = undefined;
|
nickjillings@1324
|
2342 this.type = undefined;
|
nickjillings@1406
|
2343 this.options = [];
|
nickjillings@1324
|
2344 this.statement = undefined;
|
nickjillings@1370
|
2345 this.schema = specification.schema.getAllElementsByName('commentquestion')[0];
|
nickjillings@1370
|
2346 this.decode = function(parent,xml)
|
nickjillings@1406
|
2347 {
|
nickjillings@1324
|
2348 this.id = xml.id;
|
nickjillings@2156
|
2349 this.name = xml.getAttribute('name');
|
nickjillings@1324
|
2350 this.type = xml.getAttribute('type');
|
nickjillings@1324
|
2351 this.statement = xml.getElementsByTagName('statement')[0].textContent;
|
nickjillings@1324
|
2352 var optNodes = xml.getElementsByTagName('option');
|
nickjillings@1324
|
2353 for (var i=0; i<optNodes.length; i++)
|
nickjillings@1324
|
2354 {
|
nickjillings@1324
|
2355 var optNode = optNodes[i];
|
nickjillings@1324
|
2356 this.options.push({
|
nickjillings@1324
|
2357 name: optNode.getAttribute('name'),
|
nickjillings@1324
|
2358 text: optNode.textContent
|
nickjillings@1324
|
2359 });
|
nickjillings@1406
|
2360 }
|
nickjillings@1406
|
2361 };
|
nickjillings@1324
|
2362
|
nickjillings@1406
|
2363 this.encode = function(root)
|
nickjillings@1406
|
2364 {
|
nickjillings@1372
|
2365 var node = root.createElement("commentquestion");
|
nickjillings@1372
|
2366 node.id = this.id;
|
nickjillings@1372
|
2367 node.setAttribute("type",this.type);
|
nickjillings@2156
|
2368 if (this.name != undefined){node.setAttribute("name",this.name);}
|
nickjillings@1372
|
2369 var statement = root.createElement("statement");
|
nickjillings@1372
|
2370 statement.textContent = this.statement;
|
nickjillings@1372
|
2371 node.appendChild(statement);
|
nickjillings@1372
|
2372 for (var option of this.options)
|
nickjillings@1372
|
2373 {
|
nickjillings@1372
|
2374 var child = root.createElement("option");
|
nickjillings@1372
|
2375 child.setAttribute("name",option.name);
|
nickjillings@1372
|
2376 child.textContent = option.text;
|
nickjillings@1372
|
2377 node.appendChild(child);
|
nickjillings@1372
|
2378 }
|
nickjillings@1372
|
2379 return node;
|
nickjillings@1406
|
2380 };
|
nickjillings@1406
|
2381 };
|
nickjillings@1406
|
2382
|
nickjillings@1406
|
2383 this.audioElementNode = function() {
|
nickjillings@1406
|
2384 this.url = null;
|
nickjillings@1406
|
2385 this.id = null;
|
nickjillings@2156
|
2386 this.name = null;
|
nickjillings@1406
|
2387 this.parent = null;
|
nickjillings@1324
|
2388 this.type = null;
|
nickjillings@1310
|
2389 this.marker = null;
|
nickjillings@1406
|
2390 this.enforce = false;
|
nickjillings@2130
|
2391 this.gain = 0.0;
|
nickjillings@1370
|
2392 this.schema = specification.schema.getAllElementsByName('audioelement')[0];;
|
nickjillings@1324
|
2393 this.parent = null;
|
nickjillings@1406
|
2394 this.decode = function(parent,xml)
|
nickjillings@1406
|
2395 {
|
nickjillings@1406
|
2396 this.parent = parent;
|
nickjillings@1348
|
2397 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1324
|
2398 for (var i=0; i<attributeMap.length; i++)
|
nickjillings@1426
|
2399 {
|
nickjillings@1324
|
2400 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
|
nickjillings@1324
|
2401 var projectAttr = xml.getAttribute(attributeName);
|
nickjillings@2165
|
2402 projectAttr = parent.parent.processAttribute(projectAttr,attributeMap[i],parent.parent.schema);
|
nickjillings@1324
|
2403 switch(typeof projectAttr)
|
nickjillings@1406
|
2404 {
|
nickjillings@1324
|
2405 case "number":
|
nickjillings@1324
|
2406 case "boolean":
|
nickjillings@1324
|
2407 eval('this.'+attributeName+' = '+projectAttr);
|
nickjillings@1324
|
2408 break;
|
nickjillings@1324
|
2409 case "string":
|
nickjillings@1324
|
2410 eval('this.'+attributeName+' = "'+projectAttr+'"');
|
nickjillings@1324
|
2411 break;
|
nickjillings@1455
|
2412 }
|
nickjillings@1455
|
2413 }
|
nickjillings@1324
|
2414
|
nickjillings@1406
|
2415 };
|
nickjillings@1406
|
2416 this.encode = function(root)
|
nickjillings@1406
|
2417 {
|
nickjillings@1372
|
2418 var AENode = root.createElement("audioelement");
|
nickjillings@1372
|
2419 var attributes = this.schema.getAllElementsByTagName('xs:attribute');
|
nickjillings@1372
|
2420 for (var i=0; i<attributes.length; i++)
|
nickjillings@1372
|
2421 {
|
nickjillings@1372
|
2422 var name = attributes[i].getAttribute("name");
|
nickjillings@1372
|
2423 if (name == undefined) {
|
nickjillings@1372
|
2424 name = attributes[i].getAttribute("ref");
|
nickjillings@1372
|
2425 }
|
nickjillings@1372
|
2426 if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required")
|
nickjillings@1372
|
2427 {
|
nickjillings@1372
|
2428 eval("AENode.setAttribute('"+name+"',this."+name+")");
|
nickjillings@1372
|
2429 }
|
nickjillings@1372
|
2430 }
|
nickjillings@1406
|
2431 return AENode;
|
nickjillings@1406
|
2432 };
|
nickjillings@1580
|
2433 };
|
nickjillings@1580
|
2434 };
|
nickjillings@1580
|
2435 }
|
nickjillings@1406
|
2436
|
nickjillings@1582
|
2437 function Interface(specificationObject) {
|
nickjillings@1580
|
2438 // This handles the bindings between the interface and the audioEngineContext;
|
nickjillings@1582
|
2439 this.specification = specificationObject;
|
nickjillings@1582
|
2440 this.insertPoint = document.getElementById("topLevelBody");
|
nickjillings@1580
|
2441
|
nickjillings@1324
|
2442 this.newPage = function(audioHolderObject,store)
|
nickjillings@1407
|
2443 {
|
nickjillings@1369
|
2444 audioEngineContext.newTestPage(audioHolderObject,store);
|
nickjillings@2117
|
2445 interfaceContext.commentBoxes.deleteCommentBoxes();
|
nickjillings@1407
|
2446 interfaceContext.deleteCommentQuestions();
|
nickjillings@1324
|
2447 loadTest(audioHolderObject,store);
|
nickjillings@1407
|
2448 };
|
nickjillings@1407
|
2449
|
nickjillings@1582
|
2450 // Bounded by interface!!
|
nickjillings@1582
|
2451 // Interface object MUST have an exportXMLDOM method which returns the various DOM levels
|
nickjillings@1582
|
2452 // For example, APE returns the slider position normalised in a <value> tag.
|
nickjillings@1582
|
2453 this.interfaceObjects = [];
|
nickjillings@1582
|
2454 this.interfaceObject = function(){};
|
nickjillings@1582
|
2455
|
nickjillings@1525
|
2456 this.resizeWindow = function(event)
|
nickjillings@1525
|
2457 {
|
nickjillings@1421
|
2458 popup.resize(event);
|
nickjillings@1525
|
2459 for(var i=0; i<this.commentBoxes.length; i++)
|
nickjillings@1525
|
2460 {this.commentBoxes[i].resize();}
|
nickjillings@1525
|
2461 for(var i=0; i<this.commentQuestions.length; i++)
|
nickjillings@1525
|
2462 {this.commentQuestions[i].resize();}
|
nickjillings@1525
|
2463 try
|
nickjillings@1525
|
2464 {
|
nickjillings@1525
|
2465 resizeWindow(event);
|
nickjillings@1525
|
2466 }
|
nickjillings@1525
|
2467 catch(err)
|
nickjillings@1525
|
2468 {
|
nickjillings@1525
|
2469 console.log("Warning - Interface does not have Resize option");
|
nickjillings@1525
|
2470 console.log(err);
|
nickjillings@1525
|
2471 }
|
nickjillings@1525
|
2472 };
|
nickjillings@1525
|
2473
|
nickjillings@1465
|
2474 this.returnNavigator = function()
|
nickjillings@1465
|
2475 {
|
nickjillings@1362
|
2476 var node = storage.document.createElement("navigator");
|
nickjillings@1362
|
2477 var platform = storage.document.createElement("platform");
|
nickjillings@1465
|
2478 platform.textContent = navigator.platform;
|
nickjillings@1362
|
2479 var vendor = storage.document.createElement("vendor");
|
nickjillings@1465
|
2480 vendor.textContent = navigator.vendor;
|
nickjillings@1362
|
2481 var userAgent = storage.document.createElement("uagent");
|
nickjillings@1465
|
2482 userAgent.textContent = navigator.userAgent;
|
nickjillings@1362
|
2483 var screen = storage.document.createElement("window");
|
nickjillings@1362
|
2484 screen.setAttribute('innerWidth',window.innerWidth);
|
nickjillings@1362
|
2485 screen.setAttribute('innerHeight',window.innerHeight);
|
nickjillings@1465
|
2486 node.appendChild(platform);
|
nickjillings@1465
|
2487 node.appendChild(vendor);
|
nickjillings@1465
|
2488 node.appendChild(userAgent);
|
nickjillings@1362
|
2489 node.appendChild(screen);
|
nickjillings@1465
|
2490 return node;
|
nickjillings@1465
|
2491 };
|
nickjillings@1465
|
2492
|
nickjillings@2117
|
2493 this.commentBoxes = new function() {
|
nickjillings@2117
|
2494 this.boxes = [];
|
nickjillings@2117
|
2495 this.injectPoint = null;
|
nickjillings@2117
|
2496 this.elementCommentBox = function(audioObject) {
|
nickjillings@2117
|
2497 var element = audioObject.specification;
|
nickjillings@2117
|
2498 this.audioObject = audioObject;
|
nickjillings@2117
|
2499 this.id = audioObject.id;
|
nickjillings@2117
|
2500 var audioHolderObject = audioObject.specification.parent;
|
nickjillings@2117
|
2501 // Create document objects to hold the comment boxes
|
nickjillings@2117
|
2502 this.trackComment = document.createElement('div');
|
nickjillings@2117
|
2503 this.trackComment.className = 'comment-div';
|
nickjillings@2117
|
2504 this.trackComment.id = 'comment-div-'+audioObject.id;
|
nickjillings@2117
|
2505 // Create a string next to each comment asking for a comment
|
nickjillings@2117
|
2506 this.trackString = document.createElement('span');
|
nickjillings@2117
|
2507 this.trackString.innerHTML = audioHolderObject.commentBoxPrefix+' '+audioObject.interfaceDOM.getPresentedId();
|
nickjillings@2117
|
2508 // Create the HTML5 comment box 'textarea'
|
nickjillings@2117
|
2509 this.trackCommentBox = document.createElement('textarea');
|
nickjillings@2117
|
2510 this.trackCommentBox.rows = '4';
|
nickjillings@2117
|
2511 this.trackCommentBox.cols = '100';
|
nickjillings@2117
|
2512 this.trackCommentBox.name = 'trackComment'+audioObject.id;
|
nickjillings@2117
|
2513 this.trackCommentBox.className = 'trackComment';
|
nickjillings@2117
|
2514 var br = document.createElement('br');
|
nickjillings@2117
|
2515 // Add to the holder.
|
nickjillings@2117
|
2516 this.trackComment.appendChild(this.trackString);
|
nickjillings@2117
|
2517 this.trackComment.appendChild(br);
|
nickjillings@2117
|
2518 this.trackComment.appendChild(this.trackCommentBox);
|
nickjillings@2117
|
2519
|
nickjillings@2117
|
2520 this.exportXMLDOM = function() {
|
nickjillings@2117
|
2521 var root = document.createElement('comment');
|
nickjillings@2117
|
2522 var question = document.createElement('question');
|
nickjillings@2117
|
2523 question.textContent = this.trackString.textContent;
|
nickjillings@2117
|
2524 var response = document.createElement('response');
|
nickjillings@2117
|
2525 response.textContent = this.trackCommentBox.value;
|
nickjillings@2117
|
2526 console.log("Comment frag-"+this.id+": "+response.textContent);
|
nickjillings@2117
|
2527 root.appendChild(question);
|
nickjillings@2117
|
2528 root.appendChild(response);
|
nickjillings@2117
|
2529 return root;
|
nickjillings@2117
|
2530 };
|
nickjillings@2117
|
2531 this.resize = function()
|
nickjillings@2117
|
2532 {
|
nickjillings@2117
|
2533 var boxwidth = (window.innerWidth-100)/2;
|
nickjillings@2117
|
2534 if (boxwidth >= 600)
|
nickjillings@2117
|
2535 {
|
nickjillings@2117
|
2536 boxwidth = 600;
|
nickjillings@2117
|
2537 }
|
nickjillings@2117
|
2538 else if (boxwidth < 400)
|
nickjillings@2117
|
2539 {
|
nickjillings@2117
|
2540 boxwidth = 400;
|
nickjillings@2117
|
2541 }
|
nickjillings@2117
|
2542 this.trackComment.style.width = boxwidth+"px";
|
nickjillings@2117
|
2543 this.trackCommentBox.style.width = boxwidth-6+"px";
|
nickjillings@2117
|
2544 };
|
nickjillings@2117
|
2545 this.resize();
|
nickjillings@2117
|
2546 };
|
nickjillings@2117
|
2547 this.createCommentBox = function(audioObject) {
|
nickjillings@2117
|
2548 var node = new this.elementCommentBox(audioObject);
|
nickjillings@2117
|
2549 this.boxes.push(node);
|
nickjillings@2117
|
2550 audioObject.commentDOM = node;
|
nickjillings@2117
|
2551 return node;
|
nickjillings@2117
|
2552 };
|
nickjillings@2117
|
2553 this.sortCommentBoxes = function() {
|
nickjillings@2117
|
2554 this.boxes.sort(function(a,b){return a.id - b.id;});
|
nickjillings@2117
|
2555 };
|
nickjillings@2117
|
2556
|
nickjillings@2117
|
2557 this.showCommentBoxes = function(inject, sort) {
|
nickjillings@2117
|
2558 this.injectPoint = inject;
|
nickjillings@2117
|
2559 if (sort) {this.sortCommentBoxes();}
|
nickjillings@2117
|
2560 for (var box of this.boxes) {
|
nickjillings@2117
|
2561 inject.appendChild(box.trackComment);
|
nickjillings@2117
|
2562 }
|
nickjillings@2117
|
2563 };
|
nickjillings@2117
|
2564
|
nickjillings@2117
|
2565 this.deleteCommentBoxes = function() {
|
nickjillings@2117
|
2566 if (this.injectPoint != null) {
|
nickjillings@2117
|
2567 for (var box of this.boxes) {
|
nickjillings@2117
|
2568 this.injectPoint.removeChild(box.trackComment);
|
nickjillings@2117
|
2569 }
|
nickjillings@2117
|
2570 this.injectPoint = null;
|
nickjillings@2117
|
2571 }
|
nickjillings@2117
|
2572 this.boxes = [];
|
nickjillings@2117
|
2573 };
|
nickjillings@2117
|
2574 }
|
nickjillings@1582
|
2575
|
nickjillings@2032
|
2576 this.commentQuestions = [];
|
nickjillings@2032
|
2577
|
nickjillings@2032
|
2578 this.commentBox = function(commentQuestion) {
|
nickjillings@2032
|
2579 this.specification = commentQuestion;
|
nickjillings@2032
|
2580 // Create document objects to hold the comment boxes
|
nickjillings@2032
|
2581 this.holder = document.createElement('div');
|
nickjillings@2032
|
2582 this.holder.className = 'comment-div';
|
nickjillings@2032
|
2583 // Create a string next to each comment asking for a comment
|
nickjillings@2032
|
2584 this.string = document.createElement('span');
|
nickjillings@1324
|
2585 this.string.innerHTML = commentQuestion.statement;
|
nickjillings@2032
|
2586 // Create the HTML5 comment box 'textarea'
|
nickjillings@2032
|
2587 this.textArea = document.createElement('textarea');
|
nickjillings@2032
|
2588 this.textArea.rows = '4';
|
nickjillings@2032
|
2589 this.textArea.cols = '100';
|
nickjillings@2032
|
2590 this.textArea.className = 'trackComment';
|
nickjillings@2032
|
2591 var br = document.createElement('br');
|
nickjillings@2032
|
2592 // Add to the holder.
|
nickjillings@2032
|
2593 this.holder.appendChild(this.string);
|
nickjillings@2032
|
2594 this.holder.appendChild(br);
|
nickjillings@2032
|
2595 this.holder.appendChild(this.textArea);
|
nickjillings@2032
|
2596
|
nickjillings@2097
|
2597 this.exportXMLDOM = function(storePoint) {
|
nickjillings@2097
|
2598 var root = storePoint.parent.document.createElement('comment');
|
nickjillings@2032
|
2599 root.id = this.specification.id;
|
nickjillings@2032
|
2600 root.setAttribute('type',this.specification.type);
|
b@2059
|
2601 console.log("Question: "+this.string.textContent);
|
b@2059
|
2602 console.log("Response: "+root.textContent);
|
nickjillings@2097
|
2603 var question = storePoint.parent.document.createElement('question');
|
nickjillings@2097
|
2604 question.textContent = this.string.textContent;
|
nickjillings@2097
|
2605 var response = storePoint.parent.document.createElement('response');
|
nickjillings@2097
|
2606 response.textContent = this.textArea.value;
|
nickjillings@2097
|
2607 root.appendChild(question);
|
nickjillings@2097
|
2608 root.appendChild(response);
|
nickjillings@2097
|
2609 storePoint.XMLDOM.appendChild(root);
|
nickjillings@2032
|
2610 return root;
|
nickjillings@2032
|
2611 };
|
nickjillings@1525
|
2612 this.resize = function()
|
nickjillings@1525
|
2613 {
|
nickjillings@1525
|
2614 var boxwidth = (window.innerWidth-100)/2;
|
nickjillings@1525
|
2615 if (boxwidth >= 600)
|
nickjillings@1525
|
2616 {
|
nickjillings@1525
|
2617 boxwidth = 600;
|
nickjillings@1525
|
2618 }
|
nickjillings@1525
|
2619 else if (boxwidth < 400)
|
nickjillings@1525
|
2620 {
|
nickjillings@1525
|
2621 boxwidth = 400;
|
nickjillings@1525
|
2622 }
|
nickjillings@1525
|
2623 this.holder.style.width = boxwidth+"px";
|
nickjillings@1525
|
2624 this.textArea.style.width = boxwidth-6+"px";
|
nickjillings@1525
|
2625 };
|
nickjillings@1525
|
2626 this.resize();
|
nickjillings@2032
|
2627 };
|
nickjillings@2032
|
2628
|
nickjillings@2032
|
2629 this.radioBox = function(commentQuestion) {
|
nickjillings@2032
|
2630 this.specification = commentQuestion;
|
nickjillings@2032
|
2631 // Create document objects to hold the comment boxes
|
nickjillings@2032
|
2632 this.holder = document.createElement('div');
|
nickjillings@2032
|
2633 this.holder.className = 'comment-div';
|
nickjillings@2032
|
2634 // Create a string next to each comment asking for a comment
|
nickjillings@2032
|
2635 this.string = document.createElement('span');
|
nickjillings@2032
|
2636 this.string.innerHTML = commentQuestion.statement;
|
nickjillings@2032
|
2637 var br = document.createElement('br');
|
nickjillings@2032
|
2638 // Add to the holder.
|
nickjillings@2032
|
2639 this.holder.appendChild(this.string);
|
nickjillings@2032
|
2640 this.holder.appendChild(br);
|
nickjillings@2032
|
2641 this.options = [];
|
nickjillings@2032
|
2642 this.inputs = document.createElement('div');
|
nickjillings@2032
|
2643 this.span = document.createElement('div');
|
nickjillings@2032
|
2644 this.inputs.align = 'center';
|
nickjillings@2032
|
2645 this.inputs.style.marginLeft = '12px';
|
nickjillings@2032
|
2646 this.span.style.marginLeft = '12px';
|
nickjillings@2032
|
2647 this.span.align = 'center';
|
nickjillings@2032
|
2648 this.span.style.marginTop = '15px';
|
nickjillings@2032
|
2649
|
nickjillings@2032
|
2650 var optCount = commentQuestion.options.length;
|
nickjillings@1324
|
2651 for (var optNode of commentQuestion.options)
|
nickjillings@2032
|
2652 {
|
nickjillings@2032
|
2653 var div = document.createElement('div');
|
nickjillings@1524
|
2654 div.style.width = '80px';
|
nickjillings@2032
|
2655 div.style.float = 'left';
|
nickjillings@2032
|
2656 var input = document.createElement('input');
|
nickjillings@2032
|
2657 input.type = 'radio';
|
nickjillings@2032
|
2658 input.name = commentQuestion.id;
|
nickjillings@1324
|
2659 input.setAttribute('setvalue',optNode.name);
|
nickjillings@2032
|
2660 input.className = 'comment-radio';
|
nickjillings@2032
|
2661 div.appendChild(input);
|
nickjillings@2032
|
2662 this.inputs.appendChild(div);
|
nickjillings@2032
|
2663
|
nickjillings@2032
|
2664
|
nickjillings@2032
|
2665 div = document.createElement('div');
|
nickjillings@1524
|
2666 div.style.width = '80px';
|
nickjillings@2032
|
2667 div.style.float = 'left';
|
nickjillings@2032
|
2668 div.align = 'center';
|
nickjillings@2032
|
2669 var span = document.createElement('span');
|
nickjillings@1324
|
2670 span.textContent = optNode.text;
|
nickjillings@2032
|
2671 span.className = 'comment-radio-span';
|
nickjillings@2032
|
2672 div.appendChild(span);
|
nickjillings@2032
|
2673 this.span.appendChild(div);
|
nickjillings@2032
|
2674 this.options.push(input);
|
nickjillings@2032
|
2675 }
|
nickjillings@2032
|
2676 this.holder.appendChild(this.span);
|
nickjillings@2032
|
2677 this.holder.appendChild(this.inputs);
|
nickjillings@2032
|
2678
|
nickjillings@2097
|
2679 this.exportXMLDOM = function(storePoint) {
|
nickjillings@2097
|
2680 var root = storePoint.parent.document.createElement('comment');
|
nickjillings@2032
|
2681 root.id = this.specification.id;
|
nickjillings@2032
|
2682 root.setAttribute('type',this.specification.type);
|
nickjillings@2032
|
2683 var question = document.createElement('question');
|
nickjillings@2032
|
2684 question.textContent = this.string.textContent;
|
nickjillings@2032
|
2685 var response = document.createElement('response');
|
nickjillings@2032
|
2686 var i=0;
|
nickjillings@2032
|
2687 while(this.options[i].checked == false) {
|
nickjillings@2032
|
2688 i++;
|
nickjillings@2032
|
2689 if (i >= this.options.length) {
|
nickjillings@2032
|
2690 break;
|
nickjillings@2032
|
2691 }
|
nickjillings@2032
|
2692 }
|
nickjillings@2032
|
2693 if (i >= this.options.length) {
|
nickjillings@2032
|
2694 response.textContent = 'null';
|
nickjillings@2032
|
2695 } else {
|
nickjillings@2032
|
2696 response.textContent = this.options[i].getAttribute('setvalue');
|
nickjillings@2032
|
2697 response.setAttribute('number',i);
|
nickjillings@2032
|
2698 }
|
nickjillings@1572
|
2699 console.log('Comment: '+question.textContent);
|
nickjillings@1572
|
2700 console.log('Response: '+response.textContent);
|
nickjillings@2032
|
2701 root.appendChild(question);
|
nickjillings@2032
|
2702 root.appendChild(response);
|
nickjillings@2097
|
2703 storePoint.XMLDOM.appendChild(root);
|
nickjillings@2032
|
2704 return root;
|
nickjillings@2032
|
2705 };
|
nickjillings@1525
|
2706 this.resize = function()
|
nickjillings@1525
|
2707 {
|
nickjillings@1525
|
2708 var boxwidth = (window.innerWidth-100)/2;
|
nickjillings@1525
|
2709 if (boxwidth >= 600)
|
nickjillings@1525
|
2710 {
|
nickjillings@1525
|
2711 boxwidth = 600;
|
nickjillings@1525
|
2712 }
|
nickjillings@1525
|
2713 else if (boxwidth < 400)
|
nickjillings@1525
|
2714 {
|
nickjillings@1525
|
2715 boxwidth = 400;
|
nickjillings@1525
|
2716 }
|
nickjillings@1525
|
2717 this.holder.style.width = boxwidth+"px";
|
nickjillings@1525
|
2718 var text = this.holder.children[2];
|
nickjillings@1525
|
2719 var options = this.holder.children[3];
|
nickjillings@1525
|
2720 var optCount = options.children.length;
|
nickjillings@1525
|
2721 var spanMargin = Math.floor(((boxwidth-20-(optCount*80))/(optCount))/2)+'px';
|
nickjillings@1525
|
2722 var options = options.firstChild;
|
nickjillings@1525
|
2723 var text = text.firstChild;
|
nickjillings@1525
|
2724 options.style.marginRight = spanMargin;
|
nickjillings@1525
|
2725 options.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2726 text.style.marginRight = spanMargin;
|
nickjillings@1525
|
2727 text.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2728 while(options.nextSibling != undefined)
|
nickjillings@1525
|
2729 {
|
nickjillings@1525
|
2730 options = options.nextSibling;
|
nickjillings@1525
|
2731 text = text.nextSibling;
|
nickjillings@1525
|
2732 options.style.marginRight = spanMargin;
|
nickjillings@1525
|
2733 options.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2734 text.style.marginRight = spanMargin;
|
nickjillings@1525
|
2735 text.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2736 }
|
nickjillings@1525
|
2737 };
|
nickjillings@1525
|
2738 this.resize();
|
nickjillings@2032
|
2739 };
|
nickjillings@2032
|
2740
|
nickjillings@1572
|
2741 this.checkboxBox = function(commentQuestion) {
|
nickjillings@1572
|
2742 this.specification = commentQuestion;
|
nickjillings@1572
|
2743 // Create document objects to hold the comment boxes
|
nickjillings@1572
|
2744 this.holder = document.createElement('div');
|
nickjillings@1572
|
2745 this.holder.className = 'comment-div';
|
nickjillings@1572
|
2746 // Create a string next to each comment asking for a comment
|
nickjillings@1572
|
2747 this.string = document.createElement('span');
|
nickjillings@1572
|
2748 this.string.innerHTML = commentQuestion.statement;
|
nickjillings@1572
|
2749 var br = document.createElement('br');
|
nickjillings@1572
|
2750 // Add to the holder.
|
nickjillings@1572
|
2751 this.holder.appendChild(this.string);
|
nickjillings@1572
|
2752 this.holder.appendChild(br);
|
nickjillings@1572
|
2753 this.options = [];
|
nickjillings@1572
|
2754 this.inputs = document.createElement('div');
|
nickjillings@1572
|
2755 this.span = document.createElement('div');
|
nickjillings@1572
|
2756 this.inputs.align = 'center';
|
nickjillings@1572
|
2757 this.inputs.style.marginLeft = '12px';
|
nickjillings@1572
|
2758 this.span.style.marginLeft = '12px';
|
nickjillings@1572
|
2759 this.span.align = 'center';
|
nickjillings@1572
|
2760 this.span.style.marginTop = '15px';
|
nickjillings@1572
|
2761
|
nickjillings@1572
|
2762 var optCount = commentQuestion.options.length;
|
nickjillings@1572
|
2763 for (var i=0; i<optCount; i++)
|
nickjillings@1572
|
2764 {
|
nickjillings@1572
|
2765 var div = document.createElement('div');
|
nickjillings@1524
|
2766 div.style.width = '80px';
|
nickjillings@1572
|
2767 div.style.float = 'left';
|
nickjillings@1572
|
2768 var input = document.createElement('input');
|
nickjillings@1572
|
2769 input.type = 'checkbox';
|
nickjillings@1572
|
2770 input.name = commentQuestion.id;
|
nickjillings@1572
|
2771 input.setAttribute('setvalue',commentQuestion.options[i].name);
|
nickjillings@1572
|
2772 input.className = 'comment-radio';
|
nickjillings@1572
|
2773 div.appendChild(input);
|
nickjillings@1572
|
2774 this.inputs.appendChild(div);
|
nickjillings@1572
|
2775
|
nickjillings@1572
|
2776
|
nickjillings@1572
|
2777 div = document.createElement('div');
|
nickjillings@1524
|
2778 div.style.width = '80px';
|
nickjillings@1572
|
2779 div.style.float = 'left';
|
nickjillings@1572
|
2780 div.align = 'center';
|
nickjillings@1572
|
2781 var span = document.createElement('span');
|
nickjillings@1572
|
2782 span.textContent = commentQuestion.options[i].text;
|
nickjillings@1572
|
2783 span.className = 'comment-radio-span';
|
nickjillings@1572
|
2784 div.appendChild(span);
|
nickjillings@1572
|
2785 this.span.appendChild(div);
|
nickjillings@1572
|
2786 this.options.push(input);
|
nickjillings@1572
|
2787 }
|
nickjillings@1572
|
2788 this.holder.appendChild(this.span);
|
nickjillings@1572
|
2789 this.holder.appendChild(this.inputs);
|
nickjillings@1572
|
2790
|
nickjillings@2097
|
2791 this.exportXMLDOM = function(storePoint) {
|
nickjillings@2097
|
2792 var root = storePoint.parent.document.createElement('comment');
|
nickjillings@1572
|
2793 root.id = this.specification.id;
|
nickjillings@1572
|
2794 root.setAttribute('type',this.specification.type);
|
nickjillings@1572
|
2795 var question = document.createElement('question');
|
nickjillings@1572
|
2796 question.textContent = this.string.textContent;
|
nickjillings@1572
|
2797 root.appendChild(question);
|
nickjillings@1572
|
2798 console.log('Comment: '+question.textContent);
|
nickjillings@1572
|
2799 for (var i=0; i<this.options.length; i++) {
|
nickjillings@1572
|
2800 var response = document.createElement('response');
|
nickjillings@1572
|
2801 response.textContent = this.options[i].checked;
|
nickjillings@1572
|
2802 response.setAttribute('name',this.options[i].getAttribute('setvalue'));
|
nickjillings@1572
|
2803 root.appendChild(response);
|
nickjillings@1572
|
2804 console.log('Response '+response.getAttribute('name') +': '+response.textContent);
|
nickjillings@1572
|
2805 }
|
nickjillings@2097
|
2806 storePoint.XMLDOM.appendChild(root);
|
nickjillings@1572
|
2807 return root;
|
nickjillings@1572
|
2808 };
|
nickjillings@1525
|
2809 this.resize = function()
|
nickjillings@1525
|
2810 {
|
nickjillings@1525
|
2811 var boxwidth = (window.innerWidth-100)/2;
|
nickjillings@1525
|
2812 if (boxwidth >= 600)
|
nickjillings@1525
|
2813 {
|
nickjillings@1525
|
2814 boxwidth = 600;
|
nickjillings@1525
|
2815 }
|
nickjillings@1525
|
2816 else if (boxwidth < 400)
|
nickjillings@1525
|
2817 {
|
nickjillings@1525
|
2818 boxwidth = 400;
|
nickjillings@1525
|
2819 }
|
nickjillings@1525
|
2820 this.holder.style.width = boxwidth+"px";
|
nickjillings@1525
|
2821 var text = this.holder.children[2];
|
nickjillings@1525
|
2822 var options = this.holder.children[3];
|
nickjillings@1525
|
2823 var optCount = options.children.length;
|
nickjillings@1525
|
2824 var spanMargin = Math.floor(((boxwidth-20-(optCount*80))/(optCount))/2)+'px';
|
nickjillings@1525
|
2825 var options = options.firstChild;
|
nickjillings@1525
|
2826 var text = text.firstChild;
|
nickjillings@1525
|
2827 options.style.marginRight = spanMargin;
|
nickjillings@1525
|
2828 options.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2829 text.style.marginRight = spanMargin;
|
nickjillings@1525
|
2830 text.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2831 while(options.nextSibling != undefined)
|
nickjillings@1525
|
2832 {
|
nickjillings@1525
|
2833 options = options.nextSibling;
|
nickjillings@1525
|
2834 text = text.nextSibling;
|
nickjillings@1525
|
2835 options.style.marginRight = spanMargin;
|
nickjillings@1525
|
2836 options.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2837 text.style.marginRight = spanMargin;
|
nickjillings@1525
|
2838 text.style.marginLeft = spanMargin;
|
nickjillings@1525
|
2839 }
|
nickjillings@1525
|
2840 };
|
nickjillings@1525
|
2841 this.resize();
|
nickjillings@1572
|
2842 };
|
nickjillings@1570
|
2843
|
nickjillings@2032
|
2844 this.createCommentQuestion = function(element) {
|
nickjillings@2032
|
2845 var node;
|
nickjillings@1324
|
2846 if (element.type == 'question') {
|
nickjillings@2032
|
2847 node = new this.commentBox(element);
|
nickjillings@2032
|
2848 } else if (element.type == 'radio') {
|
nickjillings@2032
|
2849 node = new this.radioBox(element);
|
nickjillings@1572
|
2850 } else if (element.type == 'checkbox') {
|
nickjillings@1572
|
2851 node = new this.checkboxBox(element);
|
nickjillings@2032
|
2852 }
|
nickjillings@2032
|
2853 this.commentQuestions.push(node);
|
nickjillings@2032
|
2854 return node;
|
nickjillings@2032
|
2855 };
|
nickjillings@1564
|
2856
|
nickjillings@2051
|
2857 this.deleteCommentQuestions = function()
|
nickjillings@2051
|
2858 {
|
nickjillings@2051
|
2859 this.commentQuestions = [];
|
nickjillings@2051
|
2860 };
|
nickjillings@2051
|
2861
|
nickjillings@1564
|
2862 this.playhead = new function()
|
nickjillings@1564
|
2863 {
|
nickjillings@1564
|
2864 this.object = document.createElement('div');
|
nickjillings@1564
|
2865 this.object.className = 'playhead';
|
nickjillings@1564
|
2866 this.object.align = 'left';
|
nickjillings@1564
|
2867 var curTime = document.createElement('div');
|
nickjillings@1564
|
2868 curTime.style.width = '50px';
|
nickjillings@1564
|
2869 this.curTimeSpan = document.createElement('span');
|
nickjillings@1564
|
2870 this.curTimeSpan.textContent = '00:00';
|
nickjillings@1564
|
2871 curTime.appendChild(this.curTimeSpan);
|
nickjillings@1564
|
2872 this.object.appendChild(curTime);
|
nickjillings@1564
|
2873 this.scrubberTrack = document.createElement('div');
|
nickjillings@1564
|
2874 this.scrubberTrack.className = 'playhead-scrub-track';
|
nickjillings@1564
|
2875
|
nickjillings@1564
|
2876 this.scrubberHead = document.createElement('div');
|
nickjillings@1564
|
2877 this.scrubberHead.id = 'playhead-scrubber';
|
nickjillings@1564
|
2878 this.scrubberTrack.appendChild(this.scrubberHead);
|
nickjillings@1564
|
2879 this.object.appendChild(this.scrubberTrack);
|
nickjillings@1564
|
2880
|
nickjillings@1564
|
2881 this.timePerPixel = 0;
|
nickjillings@1564
|
2882 this.maxTime = 0;
|
nickjillings@1564
|
2883
|
nickjillings@1567
|
2884 this.playbackObject;
|
nickjillings@1567
|
2885
|
nickjillings@1567
|
2886 this.setTimePerPixel = function(audioObject) {
|
nickjillings@1564
|
2887 //maxTime must be in seconds
|
nickjillings@1567
|
2888 this.playbackObject = audioObject;
|
nickjillings@1410
|
2889 this.maxTime = audioObject.buffer.buffer.duration;
|
nickjillings@1564
|
2890 var width = 490; //500 - 10, 5 each side of the tracker head
|
nickjillings@1567
|
2891 this.timePerPixel = this.maxTime/490;
|
nickjillings@1567
|
2892 if (this.maxTime < 60) {
|
nickjillings@1564
|
2893 this.curTimeSpan.textContent = '0.00';
|
nickjillings@1564
|
2894 } else {
|
nickjillings@1564
|
2895 this.curTimeSpan.textContent = '00:00';
|
nickjillings@1564
|
2896 }
|
nickjillings@1564
|
2897 };
|
nickjillings@1564
|
2898
|
nickjillings@1567
|
2899 this.update = function() {
|
nickjillings@1564
|
2900 // Update the playhead position, startPlay must be called
|
nickjillings@1564
|
2901 if (this.timePerPixel > 0) {
|
nickjillings@1567
|
2902 var time = this.playbackObject.getCurrentPosition();
|
nickjillings@1367
|
2903 if (time > 0 && time < this.maxTime) {
|
nickjillings@1530
|
2904 var width = 490;
|
nickjillings@1530
|
2905 var pix = Math.floor(time/this.timePerPixel);
|
nickjillings@1530
|
2906 this.scrubberHead.style.left = pix+'px';
|
nickjillings@1530
|
2907 if (this.maxTime > 60.0) {
|
nickjillings@1530
|
2908 var secs = time%60;
|
nickjillings@1530
|
2909 var mins = Math.floor((time-secs)/60);
|
nickjillings@1530
|
2910 secs = secs.toString();
|
nickjillings@1530
|
2911 secs = secs.substr(0,2);
|
nickjillings@1530
|
2912 mins = mins.toString();
|
nickjillings@1530
|
2913 this.curTimeSpan.textContent = mins+':'+secs;
|
nickjillings@1530
|
2914 } else {
|
nickjillings@1530
|
2915 time = time.toString();
|
nickjillings@1530
|
2916 this.curTimeSpan.textContent = time.substr(0,4);
|
nickjillings@1530
|
2917 }
|
nickjillings@1564
|
2918 } else {
|
nickjillings@1530
|
2919 this.scrubberHead.style.left = '0px';
|
nickjillings@1530
|
2920 if (this.maxTime < 60) {
|
nickjillings@1530
|
2921 this.curTimeSpan.textContent = '0.00';
|
nickjillings@1530
|
2922 } else {
|
nickjillings@1530
|
2923 this.curTimeSpan.textContent = '00:00';
|
nickjillings@1530
|
2924 }
|
nickjillings@1564
|
2925 }
|
nickjillings@1564
|
2926 }
|
nickjillings@1564
|
2927 };
|
nickjillings@1567
|
2928
|
nickjillings@1567
|
2929 this.interval = undefined;
|
nickjillings@1567
|
2930
|
nickjillings@1567
|
2931 this.start = function() {
|
nickjillings@1567
|
2932 if (this.playbackObject != undefined && this.interval == undefined) {
|
nickjillings@1530
|
2933 if (this.maxTime < 60) {
|
nickjillings@1530
|
2934 this.interval = setInterval(function(){interfaceContext.playhead.update();},10);
|
nickjillings@1530
|
2935 } else {
|
nickjillings@1530
|
2936 this.interval = setInterval(function(){interfaceContext.playhead.update();},100);
|
nickjillings@1530
|
2937 }
|
nickjillings@1567
|
2938 }
|
nickjillings@1567
|
2939 };
|
nickjillings@1567
|
2940 this.stop = function() {
|
nickjillings@1567
|
2941 clearInterval(this.interval);
|
nickjillings@1567
|
2942 this.interval = undefined;
|
nickjillings@2101
|
2943 this.scrubberHead.style.left = '0px';
|
nickjillings@1530
|
2944 if (this.maxTime < 60) {
|
nickjillings@1530
|
2945 this.curTimeSpan.textContent = '0.00';
|
nickjillings@1530
|
2946 } else {
|
nickjillings@1530
|
2947 this.curTimeSpan.textContent = '00:00';
|
nickjillings@1530
|
2948 }
|
nickjillings@1567
|
2949 };
|
nickjillings@1564
|
2950 };
|
nickjillings@1354
|
2951
|
nickjillings@1354
|
2952 this.volume = new function()
|
nickjillings@1354
|
2953 {
|
nickjillings@1354
|
2954 // An in-built volume module which can be viewed on page
|
nickjillings@1354
|
2955 // Includes trackers on page-by-page data
|
nickjillings@1354
|
2956 // Volume does NOT reset to 0dB on each page load
|
nickjillings@1354
|
2957 this.valueLin = 1.0;
|
nickjillings@1354
|
2958 this.valueDB = 0.0;
|
nickjillings@1354
|
2959 this.object = document.createElement('div');
|
nickjillings@1354
|
2960 this.object.id = 'master-volume-holder';
|
nickjillings@1354
|
2961 this.slider = document.createElement('input');
|
nickjillings@1354
|
2962 this.slider.id = 'master-volume-control';
|
nickjillings@1354
|
2963 this.slider.type = 'range';
|
nickjillings@1354
|
2964 this.valueText = document.createElement('span');
|
nickjillings@1354
|
2965 this.valueText.id = 'master-volume-feedback';
|
nickjillings@1354
|
2966 this.valueText.textContent = '0dB';
|
nickjillings@1354
|
2967
|
nickjillings@1354
|
2968 this.slider.min = -60;
|
nickjillings@1354
|
2969 this.slider.max = 12;
|
nickjillings@1354
|
2970 this.slider.value = 0;
|
nickjillings@1354
|
2971 this.slider.step = 1;
|
nickjillings@1354
|
2972 this.slider.onmousemove = function(event)
|
nickjillings@1354
|
2973 {
|
nickjillings@1354
|
2974 interfaceContext.volume.valueDB = event.currentTarget.value;
|
nickjillings@1354
|
2975 interfaceContext.volume.valueLin = decibelToLinear(interfaceContext.volume.valueDB);
|
nickjillings@1354
|
2976 interfaceContext.volume.valueText.textContent = interfaceContext.volume.valueDB+'dB';
|
nickjillings@1354
|
2977 audioEngineContext.outputGain.gain.value = interfaceContext.volume.valueLin;
|
nickjillings@1354
|
2978 }
|
nickjillings@1354
|
2979 this.slider.onmouseup = function(event)
|
nickjillings@1354
|
2980 {
|
nickjillings@2100
|
2981 var storePoint = testState.currentStore.XMLDOM.getElementsByTagName('metric')[0].getAllElementsByName('volumeTracker');
|
nickjillings@1354
|
2982 if (storePoint.length == 0)
|
nickjillings@1354
|
2983 {
|
nickjillings@1354
|
2984 storePoint = storage.document.createElement('metricresult');
|
nickjillings@1354
|
2985 storePoint.setAttribute('name','volumeTracker');
|
nickjillings@2100
|
2986 testState.currentStore.XMLDOM.getElementsByTagName('metric')[0].appendChild(storePoint);
|
nickjillings@1354
|
2987 }
|
nickjillings@1354
|
2988 else {
|
nickjillings@1354
|
2989 storePoint = storePoint[0];
|
nickjillings@1354
|
2990 }
|
nickjillings@1354
|
2991 var node = storage.document.createElement('movement');
|
nickjillings@1354
|
2992 node.setAttribute('test-time',audioEngineContext.timer.getTestTime());
|
nickjillings@1354
|
2993 node.setAttribute('volume',interfaceContext.volume.valueDB);
|
nickjillings@1354
|
2994 node.setAttribute('format','dBFS');
|
nickjillings@1354
|
2995 storePoint.appendChild(node);
|
nickjillings@1354
|
2996 }
|
nickjillings@1354
|
2997
|
nickjillings@1355
|
2998 var title = document.createElement('div');
|
nickjillings@1355
|
2999 title.innerHTML = '<span>Master Volume Control</span>';
|
nickjillings@1355
|
3000 title.style.fontSize = '0.75em';
|
nickjillings@1355
|
3001 title.style.width = "100%";
|
nickjillings@1355
|
3002 title.align = 'center';
|
nickjillings@1355
|
3003 this.object.appendChild(title);
|
nickjillings@1355
|
3004
|
nickjillings@1354
|
3005 this.object.appendChild(this.slider);
|
nickjillings@1354
|
3006 this.object.appendChild(this.valueText);
|
nickjillings@1354
|
3007 }
|
nickjillings@2049
|
3008 // Global Checkers
|
nickjillings@2049
|
3009 // These functions will help enforce the checkers
|
nickjillings@2049
|
3010 this.checkHiddenAnchor = function()
|
nickjillings@2049
|
3011 {
|
nickjillings@1324
|
3012 for (var ao of audioEngineContext.audioObjects)
|
nickjillings@2049
|
3013 {
|
nickjillings@1324
|
3014 if (ao.specification.type == "anchor")
|
nickjillings@2049
|
3015 {
|
nickjillings@1325
|
3016 if (ao.interfaceDOM.getValue() > (ao.specification.marker/100) && ao.specification.marker > 0) {
|
nickjillings@1324
|
3017 // Anchor is not set below
|
nickjillings@1324
|
3018 console.log('Anchor node not below marker value');
|
nickjillings@1324
|
3019 alert('Please keep listening');
|
nickjillings@1367
|
3020 this.storeErrorNode('Anchor node not below marker value');
|
nickjillings@1324
|
3021 return false;
|
nickjillings@1324
|
3022 }
|
nickjillings@2049
|
3023 }
|
nickjillings@2049
|
3024 }
|
nickjillings@2049
|
3025 return true;
|
nickjillings@2049
|
3026 };
|
nickjillings@2049
|
3027
|
nickjillings@2049
|
3028 this.checkHiddenReference = function()
|
nickjillings@2049
|
3029 {
|
nickjillings@1324
|
3030 for (var ao of audioEngineContext.audioObjects)
|
nickjillings@2049
|
3031 {
|
nickjillings@1324
|
3032 if (ao.specification.type == "reference")
|
nickjillings@2049
|
3033 {
|
nickjillings@1325
|
3034 if (ao.interfaceDOM.getValue() < (ao.specification.marker/100) && ao.specification.marker > 0) {
|
nickjillings@1324
|
3035 // Anchor is not set below
|
nickjillings@1367
|
3036 console.log('Reference node not above marker value');
|
nickjillings@1367
|
3037 this.storeErrorNode('Reference node not above marker value');
|
nickjillings@1324
|
3038 alert('Please keep listening');
|
nickjillings@1324
|
3039 return false;
|
nickjillings@1324
|
3040 }
|
nickjillings@2049
|
3041 }
|
nickjillings@2049
|
3042 }
|
nickjillings@2049
|
3043 return true;
|
nickjillings@2049
|
3044 };
|
nickjillings@1474
|
3045
|
nickjillings@1474
|
3046 this.checkFragmentsFullyPlayed = function ()
|
nickjillings@1474
|
3047 {
|
nickjillings@1474
|
3048 // Checks the entire file has been played back
|
nickjillings@1474
|
3049 // NOTE ! This will return true IF playback is Looped!!!
|
nickjillings@1474
|
3050 if (audioEngineContext.loopPlayback)
|
nickjillings@1474
|
3051 {
|
nickjillings@1474
|
3052 console.log("WARNING - Looped source: Cannot check fragments are fully played");
|
nickjillings@1474
|
3053 return true;
|
nickjillings@1474
|
3054 }
|
nickjillings@1474
|
3055 var check_pass = true;
|
nickjillings@1474
|
3056 var error_obj = [];
|
nickjillings@1474
|
3057 for (var i = 0; i<audioEngineContext.audioObjects.length; i++)
|
nickjillings@1474
|
3058 {
|
nickjillings@1474
|
3059 var object = audioEngineContext.audioObjects[i];
|
nickjillings@1393
|
3060 var time = object.buffer.buffer.duration;
|
nickjillings@1474
|
3061 var metric = object.metric;
|
nickjillings@1474
|
3062 var passed = false;
|
nickjillings@1474
|
3063 for (var j=0; j<metric.listenTracker.length; j++)
|
nickjillings@1474
|
3064 {
|
nickjillings@1474
|
3065 var bt = metric.listenTracker[j].getElementsByTagName('buffertime');
|
nickjillings@1474
|
3066 var start_time = Number(bt[0].getAttribute('start'));
|
nickjillings@1474
|
3067 var stop_time = Number(bt[0].getAttribute('stop'));
|
nickjillings@1474
|
3068 var delta = stop_time - start_time;
|
nickjillings@1474
|
3069 if (delta >= time)
|
nickjillings@1474
|
3070 {
|
nickjillings@1474
|
3071 passed = true;
|
nickjillings@1474
|
3072 break;
|
nickjillings@1474
|
3073 }
|
nickjillings@1474
|
3074 }
|
nickjillings@1474
|
3075 if (passed == false)
|
nickjillings@1474
|
3076 {
|
nickjillings@1474
|
3077 check_pass = false;
|
nickjillings@1290
|
3078 console.log("Continue listening to track-"+object.interfaceDOM.getPresentedId());
|
nickjillings@1290
|
3079 error_obj.push(object.interfaceDOM.getPresentedId());
|
nickjillings@1474
|
3080 }
|
nickjillings@1474
|
3081 }
|
nickjillings@1474
|
3082 if (check_pass == false)
|
nickjillings@1474
|
3083 {
|
nickjillings@1393
|
3084 var str_start = "You have not completely listened to fragments ";
|
nickjillings@1474
|
3085 for (var i=0; i<error_obj.length; i++)
|
nickjillings@1474
|
3086 {
|
nickjillings@1474
|
3087 str_start += error_obj[i];
|
nickjillings@1474
|
3088 if (i != error_obj.length-1)
|
nickjillings@1474
|
3089 {
|
nickjillings@1474
|
3090 str_start += ', ';
|
nickjillings@1474
|
3091 }
|
nickjillings@1474
|
3092 }
|
nickjillings@1474
|
3093 str_start += ". Please keep listening";
|
nickjillings@1474
|
3094 console.log("[ALERT]: "+str_start);
|
nickjillings@1367
|
3095 this.storeErrorNode("[ALERT]: "+str_start);
|
nickjillings@1474
|
3096 alert(str_start);
|
nickjillings@1474
|
3097 }
|
nickjillings@1474
|
3098 };
|
nickjillings@1399
|
3099 this.checkAllMoved = function()
|
nickjillings@1399
|
3100 {
|
nickjillings@1399
|
3101 var str = "You have not moved ";
|
nickjillings@1399
|
3102 var failed = [];
|
nickjillings@1340
|
3103 for (var ao of audioEngineContext.audioObjects)
|
nickjillings@1399
|
3104 {
|
nickjillings@1340
|
3105 if(ao.metric.wasMoved == false && ao.interfaceDOM.canMove() == true)
|
nickjillings@1399
|
3106 {
|
nickjillings@1340
|
3107 failed.push(ao.interfaceDOM.getPresentedId());
|
nickjillings@1399
|
3108 }
|
nickjillings@1399
|
3109 }
|
nickjillings@1399
|
3110 if (failed.length == 0)
|
nickjillings@1399
|
3111 {
|
nickjillings@1399
|
3112 return true;
|
nickjillings@1399
|
3113 } else if (failed.length == 1)
|
nickjillings@1399
|
3114 {
|
nickjillings@1399
|
3115 str += 'track '+failed[0];
|
nickjillings@1399
|
3116 } else {
|
nickjillings@1399
|
3117 str += 'tracks ';
|
nickjillings@1399
|
3118 for (var i=0; i<failed.length-1; i++)
|
nickjillings@1399
|
3119 {
|
nickjillings@1399
|
3120 str += failed[i]+', ';
|
nickjillings@1399
|
3121 }
|
nickjillings@1399
|
3122 str += 'and '+failed[i];
|
nickjillings@1399
|
3123 }
|
nickjillings@1399
|
3124 str +='.';
|
nickjillings@1399
|
3125 alert(str);
|
nickjillings@1399
|
3126 console.log(str);
|
nickjillings@1367
|
3127 this.storeErrorNode(str);
|
nickjillings@1399
|
3128 return false;
|
nickjillings@1399
|
3129 };
|
nickjillings@1399
|
3130 this.checkAllPlayed = function()
|
nickjillings@1399
|
3131 {
|
nickjillings@1399
|
3132 var str = "You have not played ";
|
nickjillings@1399
|
3133 var failed = [];
|
nickjillings@1340
|
3134 for (var ao of audioEngineContext.audioObjects)
|
nickjillings@1399
|
3135 {
|
nickjillings@1340
|
3136 if(ao.metric.wasListenedTo == false)
|
nickjillings@1399
|
3137 {
|
nickjillings@1340
|
3138 failed.push(ao.interfaceDOM.getPresentedId());
|
nickjillings@1399
|
3139 }
|
nickjillings@1399
|
3140 }
|
nickjillings@1399
|
3141 if (failed.length == 0)
|
nickjillings@1399
|
3142 {
|
nickjillings@1399
|
3143 return true;
|
nickjillings@1399
|
3144 } else if (failed.length == 1)
|
nickjillings@1399
|
3145 {
|
nickjillings@1399
|
3146 str += 'track '+failed[0];
|
nickjillings@1399
|
3147 } else {
|
nickjillings@1399
|
3148 str += 'tracks ';
|
nickjillings@1399
|
3149 for (var i=0; i<failed.length-1; i++)
|
nickjillings@1399
|
3150 {
|
nickjillings@1399
|
3151 str += failed[i]+', ';
|
nickjillings@1399
|
3152 }
|
nickjillings@1399
|
3153 str += 'and '+failed[i];
|
nickjillings@1399
|
3154 }
|
nickjillings@1399
|
3155 str +='.';
|
nickjillings@1399
|
3156 alert(str);
|
nickjillings@1399
|
3157 console.log(str);
|
nickjillings@1367
|
3158 this.storeErrorNode(str);
|
nickjillings@1399
|
3159 return false;
|
nickjillings@1399
|
3160 };
|
nickjillings@1367
|
3161
|
nickjillings@1367
|
3162 this.storeErrorNode = function(errorMessage)
|
nickjillings@1367
|
3163 {
|
nickjillings@1367
|
3164 var time = audioEngineContext.timer.getTestTime();
|
nickjillings@1367
|
3165 var node = storage.document.createElement('error');
|
nickjillings@1367
|
3166 node.setAttribute('time',time);
|
nickjillings@1367
|
3167 node.textContent = errorMessage;
|
nickjillings@1367
|
3168 testState.currentStore.XMLDOM.appendChild(node);
|
nickjillings@1367
|
3169 };
|
nickjillings@1324
|
3170 }
|
nickjillings@1324
|
3171
|
nickjillings@1324
|
3172 function Storage()
|
nickjillings@1324
|
3173 {
|
nickjillings@1324
|
3174 // Holds results in XML format until ready for collection
|
nickjillings@1324
|
3175 this.globalPreTest = null;
|
nickjillings@1324
|
3176 this.globalPostTest = null;
|
nickjillings@1324
|
3177 this.testPages = [];
|
nickjillings@1294
|
3178 this.document = null;
|
nickjillings@1294
|
3179 this.root = null;
|
nickjillings@1324
|
3180 this.state = 0;
|
nickjillings@1324
|
3181
|
nickjillings@1294
|
3182 this.initialise = function(existingStore)
|
nickjillings@1324
|
3183 {
|
nickjillings@1294
|
3184 if (existingStore == undefined) {
|
nickjillings@2147
|
3185 // We need to get the sessionKey
|
nickjillings@2147
|
3186 this.SessionKey.generateKey();
|
nickjillings@1294
|
3187 this.document = document.implementation.createDocument(null,"waetresult");
|
nickjillings@1294
|
3188 this.root = this.document.childNodes[0];
|
nickjillings@2150
|
3189 var projectDocument = specification.projectXML;
|
nickjillings@2150
|
3190 projectDocument.setAttribute('file-name',url);
|
nickjillings@2150
|
3191 this.root.appendChild(projectDocument);
|
nickjillings@2150
|
3192 this.root.appendChild(returnDateNode());
|
nickjillings@2150
|
3193 this.root.appendChild(interfaceContext.returnNavigator());
|
nickjillings@2147
|
3194 } else {
|
nickjillings@1294
|
3195 this.document = existingStore;
|
nickjillings@1294
|
3196 this.root = existingStore.children[0];
|
nickjillings@1294
|
3197 this.SessionKey.key = this.root.getAttribute("key");
|
nickjillings@2147
|
3198 }
|
nickjillings@2150
|
3199 if (specification.preTest != undefined){this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest);}
|
nickjillings@1294
|
3200 if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);}
|
nickjillings@1324
|
3201 };
|
nickjillings@2147
|
3202
|
nickjillings@2147
|
3203 this.SessionKey = {
|
nickjillings@2147
|
3204 key: null,
|
nickjillings@2147
|
3205 request: new XMLHttpRequest(),
|
nickjillings@2147
|
3206 parent: this,
|
nickjillings@2147
|
3207 handleEvent: function() {
|
nickjillings@2147
|
3208 var parse = new DOMParser();
|
nickjillings@2147
|
3209 var xml = parse.parseFromString(this.request.response,"text/xml");
|
nickjillings@2147
|
3210 if (xml.getAllElementsByTagName("state")[0].textContent == "OK") {
|
nickjillings@2147
|
3211 this.key = xml.getAllElementsByTagName("key")[0].textContent;
|
nickjillings@2150
|
3212 this.parent.root.setAttribute("key",this.key);
|
nickjillings@2150
|
3213 this.parent.root.setAttribute("state","empty");
|
nickjillings@2147
|
3214 } else {
|
nickjillings@2147
|
3215 this.generateKey();
|
nickjillings@2147
|
3216 }
|
nickjillings@2147
|
3217 },
|
nickjillings@2147
|
3218 generateKey: function() {
|
nickjillings@2147
|
3219 var temp_key = randomString(32);
|
nickjillings@2147
|
3220 this.request.open("GET","keygen.php?key="+temp_key,true);
|
nickjillings@2147
|
3221 this.request.addEventListener("load",this);
|
nickjillings@2147
|
3222 this.request.send();
|
nickjillings@2149
|
3223 },
|
nickjillings@2150
|
3224 update: function() {
|
nickjillings@2150
|
3225 this.parent.root.setAttribute("state","update");
|
nickjillings@2150
|
3226 var xmlhttp = new XMLHttpRequest();
|
nickjillings@2150
|
3227 xmlhttp.open("POST",specification.projectReturn+"?key="+this.key);
|
nickjillings@2150
|
3228 xmlhttp.setRequestHeader('Content-Type', 'text/xml');
|
nickjillings@2150
|
3229 xmlhttp.onerror = function(){
|
nickjillings@2150
|
3230 console.log('Error updating file to server!');
|
nickjillings@2150
|
3231 };
|
nickjillings@2150
|
3232 var hold = document.createElement("div");
|
nickjillings@2150
|
3233 var clone = this.parent.root.cloneNode(true);
|
nickjillings@2150
|
3234 hold.appendChild(clone);
|
nickjillings@2150
|
3235 xmlhttp.onload = function() {
|
nickjillings@2150
|
3236 if (this.status >= 300) {
|
nickjillings@2150
|
3237 console.log("WARNING - Could not update at this time");
|
nickjillings@2150
|
3238 } else {
|
nickjillings@2150
|
3239 var parser = new DOMParser();
|
nickjillings@2150
|
3240 var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml");
|
nickjillings@2150
|
3241 var response = xmlDoc.getElementsByTagName('response')[0];
|
nickjillings@2150
|
3242 if (response.getAttribute("state") == "OK") {
|
nickjillings@2150
|
3243 var file = response.getElementsByTagName("file")[0];
|
nickjillings@2150
|
3244 console.log("Intermediate save: OK, written "+file.getAttribute("bytes")+"B");
|
nickjillings@2150
|
3245 } else {
|
nickjillings@2150
|
3246 var message = response.getElementsByTagName("message");
|
nickjillings@2150
|
3247 console.log("Intermediate save: Error! "+message.textContent);
|
nickjillings@2150
|
3248 }
|
nickjillings@2149
|
3249 }
|
nickjillings@2149
|
3250 }
|
nickjillings@2150
|
3251 xmlhttp.send([hold.innerHTML]);
|
nickjillings@2147
|
3252 }
|
nickjillings@2147
|
3253 }
|
nickjillings@1324
|
3254
|
nickjillings@1324
|
3255 this.createTestPageStore = function(specification)
|
nickjillings@1324
|
3256 {
|
nickjillings@1324
|
3257 var store = new this.pageNode(this,specification);
|
nickjillings@1324
|
3258 this.testPages.push(store);
|
nickjillings@1324
|
3259 return this.testPages[this.testPages.length-1];
|
nickjillings@1324
|
3260 };
|
nickjillings@1324
|
3261
|
nickjillings@1324
|
3262 this.surveyNode = function(parent,root,specification)
|
nickjillings@1324
|
3263 {
|
nickjillings@1324
|
3264 this.specification = specification;
|
nickjillings@1324
|
3265 this.parent = parent;
|
nickjillings@1294
|
3266 this.state = "empty";
|
nickjillings@1324
|
3267 this.XMLDOM = this.parent.document.createElement('survey');
|
nickjillings@1324
|
3268 this.XMLDOM.setAttribute('location',this.specification.location);
|
nickjillings@1294
|
3269 this.XMLDOM.setAttribute("state",this.state);
|
nickjillings@1324
|
3270 for (var optNode of this.specification.options)
|
nickjillings@1324
|
3271 {
|
nickjillings@1324
|
3272 if (optNode.type != 'statement')
|
nickjillings@1324
|
3273 {
|
nickjillings@1324
|
3274 var node = this.parent.document.createElement('surveyresult');
|
nickjillings@1294
|
3275 node.setAttribute("ref",optNode.id);
|
nickjillings@1324
|
3276 node.setAttribute('type',optNode.type);
|
nickjillings@1324
|
3277 this.XMLDOM.appendChild(node);
|
nickjillings@1324
|
3278 }
|
nickjillings@1324
|
3279 }
|
nickjillings@1324
|
3280 root.appendChild(this.XMLDOM);
|
nickjillings@1324
|
3281
|
nickjillings@1324
|
3282 this.postResult = function(node)
|
nickjillings@1324
|
3283 {
|
nickjillings@1324
|
3284 // From popup: node is the popupOption node containing both spec. and results
|
nickjillings@1324
|
3285 // ID is the position
|
nickjillings@1324
|
3286 if (node.specification.type == 'statement'){return;}
|
nickjillings@1294
|
3287 var surveyresult = this.XMLDOM.children[0];
|
nickjillings@1294
|
3288 while(surveyresult != null) {
|
nickjillings@1294
|
3289 if (surveyresult.getAttribute("ref") == node.specification.id)
|
nickjillings@1294
|
3290 {
|
nickjillings@1294
|
3291 break;
|
nickjillings@1294
|
3292 }
|
nickjillings@1294
|
3293 surveyresult = surveyresult.nextElementSibling;
|
nickjillings@1294
|
3294 }
|
nickjillings@1324
|
3295 switch(node.specification.type)
|
nickjillings@1324
|
3296 {
|
nickjillings@1324
|
3297 case "number":
|
nickjillings@1324
|
3298 case "question":
|
nickjillings@1324
|
3299 var child = this.parent.document.createElement('response');
|
nickjillings@1324
|
3300 child.textContent = node.response;
|
nickjillings@1324
|
3301 surveyresult.appendChild(child);
|
nickjillings@1324
|
3302 break;
|
nickjillings@1324
|
3303 case "radio":
|
nickjillings@1324
|
3304 var child = this.parent.document.createElement('response');
|
nickjillings@1324
|
3305 child.setAttribute('name',node.response.name);
|
nickjillings@1324
|
3306 child.textContent = node.response.text;
|
nickjillings@1324
|
3307 surveyresult.appendChild(child);
|
nickjillings@1324
|
3308 break;
|
nickjillings@1324
|
3309 case "checkbox":
|
nickjillings@1324
|
3310 for (var i=0; i<node.response.length; i++)
|
nickjillings@1324
|
3311 {
|
nickjillings@1324
|
3312 var checkNode = this.parent.document.createElement('response');
|
nickjillings@1347
|
3313 checkNode.setAttribute('name',node.response[i].name);
|
nickjillings@1347
|
3314 checkNode.setAttribute('checked',node.response[i].checked);
|
nickjillings@1326
|
3315 surveyresult.appendChild(checkNode);
|
nickjillings@1324
|
3316 }
|
nickjillings@1324
|
3317 break;
|
nickjillings@1324
|
3318 }
|
nickjillings@1324
|
3319 };
|
nickjillings@1294
|
3320 this.complete = function() {
|
nickjillings@1294
|
3321 this.state = "complete";
|
nickjillings@1294
|
3322 this.XMLDOM.setAttribute("state",this.state);
|
nickjillings@1294
|
3323 }
|
nickjillings@1324
|
3324 };
|
nickjillings@1324
|
3325
|
nickjillings@1324
|
3326 this.pageNode = function(parent,specification)
|
nickjillings@1324
|
3327 {
|
nickjillings@1324
|
3328 // Create one store per test page
|
nickjillings@1324
|
3329 this.specification = specification;
|
nickjillings@1324
|
3330 this.parent = parent;
|
nickjillings@1294
|
3331 this.state = "empty";
|
nickjillings@1324
|
3332 this.XMLDOM = this.parent.document.createElement('page');
|
nickjillings@1294
|
3333 this.XMLDOM.setAttribute('ref',specification.id);
|
nickjillings@1324
|
3334 this.XMLDOM.setAttribute('presentedId',specification.presentedId);
|
nickjillings@1294
|
3335 this.XMLDOM.setAttribute("state",this.state);
|
nickjillings@1345
|
3336 if (specification.preTest != undefined){this.preTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.preTest);}
|
nickjillings@1345
|
3337 if (specification.postTest != undefined){this.postTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.postTest);}
|
nickjillings@1324
|
3338
|
nickjillings@1324
|
3339 // Add any page metrics
|
nickjillings@1324
|
3340 var page_metric = this.parent.document.createElement('metric');
|
nickjillings@1324
|
3341 this.XMLDOM.appendChild(page_metric);
|
nickjillings@1324
|
3342
|
nickjillings@1324
|
3343 // Add the audioelement
|
nickjillings@1324
|
3344 for (var element of this.specification.audioElements)
|
nickjillings@1324
|
3345 {
|
nickjillings@1324
|
3346 var aeNode = this.parent.document.createElement('audioelement');
|
nickjillings@1294
|
3347 aeNode.setAttribute('ref',element.id);
|
nickjillings@1294
|
3348 if (element.name != undefined){aeNode.setAttribute('name',element.name)};
|
nickjillings@1324
|
3349 aeNode.setAttribute('type',element.type);
|
nickjillings@1324
|
3350 aeNode.setAttribute('url', element.url);
|
nickjillings@1324
|
3351 aeNode.setAttribute('gain', element.gain);
|
nickjillings@1324
|
3352 if (element.type == 'anchor' || element.type == 'reference')
|
nickjillings@1324
|
3353 {
|
nickjillings@1324
|
3354 if (element.marker > 0)
|
nickjillings@1324
|
3355 {
|
nickjillings@1324
|
3356 aeNode.setAttribute('marker',element.marker);
|
nickjillings@1324
|
3357 }
|
nickjillings@1324
|
3358 }
|
nickjillings@1324
|
3359 var ae_metric = this.parent.document.createElement('metric');
|
nickjillings@1324
|
3360 aeNode.appendChild(ae_metric);
|
nickjillings@1324
|
3361 this.XMLDOM.appendChild(aeNode);
|
nickjillings@1324
|
3362 }
|
nickjillings@1324
|
3363
|
nickjillings@1324
|
3364 this.parent.root.appendChild(this.XMLDOM);
|
nickjillings@1294
|
3365
|
nickjillings@1294
|
3366 this.complete = function() {
|
nickjillings@1294
|
3367 this.state = "complete";
|
nickjillings@1294
|
3368 this.XMLDOM.setAttribute("state","complete");
|
nickjillings@1294
|
3369 }
|
nickjillings@1324
|
3370 };
|
nickjillings@2150
|
3371 this.update = function() {
|
nickjillings@2150
|
3372 this.SessionKey.update();
|
nickjillings@2150
|
3373 }
|
nickjillings@1324
|
3374 this.finish = function()
|
nickjillings@1324
|
3375 {
|
nickjillings@1324
|
3376 if (this.state == 0)
|
nickjillings@1324
|
3377 {
|
nickjillings@2150
|
3378 this.update();
|
nickjillings@1324
|
3379 }
|
nickjillings@1324
|
3380 this.state = 1;
|
nickjillings@1324
|
3381 return this.root;
|
nickjillings@1324
|
3382 };
|
nickjillings@1324
|
3383 }
|