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