Mercurial > hg > webaudioevaluationtool
comparison js/core.js @ 2677:68bc1003770a
Fixed Several JSHint issues. Functionalised the popup / survey manager
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Wed, 01 Mar 2017 10:15:12 +0000 |
parents | d75db08e5801 |
children | e446c9b43cd9 |
comparison
equal
deleted
inserted
replaced
2654:a75c78c40110 | 2677:68bc1003770a |
---|---|
46 // 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 |
47 XMLDocument.prototype.getAllElementsByName = function (name) { | 47 XMLDocument.prototype.getAllElementsByName = function (name) { |
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 name = String(name); | 54 name = String(name); |
55 var selected = []; | 55 var selected = []; |
56 var node = this.firstElementChild; | 56 var node = this.firstElementChild; |
57 while (node != null) { | 57 while (node !== null) { |
58 if (node.getAttribute('name') == name) { | 58 if (node.getAttribute('name') == name) { |
59 selected.push(node); | 59 selected.push(node); |
60 } | 60 } |
61 if (node.childElementCount > 0) { | 61 if (node.childElementCount > 0) { |
62 selected = selected.concat(node.getAllElementsByName(name)); | 62 selected = selected.concat(node.getAllElementsByName(name)); |
63 } | 63 } |
64 node = node.nextElementSibling; | 64 node = node.nextElementSibling; |
65 } | 65 } |
66 return selected; | 66 return selected; |
67 } | 67 }; |
68 | 68 |
69 XMLDocument.prototype.getAllElementsByTagName = function (name) { | 69 XMLDocument.prototype.getAllElementsByTagName = function (name) { |
70 name = String(name); | 70 name = String(name); |
71 var selected = this.documentElement.getAllElementsByTagName(name); | 71 var selected = this.documentElement.getAllElementsByTagName(name); |
72 return selected; | 72 return selected; |
73 } | 73 }; |
74 | 74 |
75 Element.prototype.getAllElementsByTagName = function (name) { | 75 Element.prototype.getAllElementsByTagName = function (name) { |
76 name = String(name); | 76 name = String(name); |
77 var selected = []; | 77 var selected = []; |
78 var node = this.firstElementChild; | 78 var node = this.firstElementChild; |
79 while (node != null) { | 79 while (node !== null) { |
80 if (node.nodeName == name) { | 80 if (node.nodeName == name) { |
81 selected.push(node); | 81 selected.push(node); |
82 } | 82 } |
83 if (node.childElementCount > 0) { | 83 if (node.childElementCount > 0) { |
84 selected = selected.concat(node.getAllElementsByTagName(name)); | 84 selected = selected.concat(node.getAllElementsByTagName(name)); |
85 } | 85 } |
86 node = node.nextElementSibling; | 86 node = node.nextElementSibling; |
87 } | 87 } |
88 return selected; | 88 return selected; |
89 } | 89 }; |
90 | 90 |
91 // Firefox does not have an XMLDocument.prototype.getElementsByName | 91 // Firefox does not have an XMLDocument.prototype.getElementsByName |
92 if (typeof XMLDocument.prototype.getElementsByName != "function") { | 92 if (typeof XMLDocument.prototype.getElementsByName != "function") { |
93 XMLDocument.prototype.getElementsByName = function (name) { | 93 XMLDocument.prototype.getElementsByName = function (name) { |
94 name = String(name); | 94 name = String(name); |
95 var node = this.documentElement.firstElementChild; | 95 var node = this.documentElement.firstElementChild; |
96 var selected = []; | 96 var selected = []; |
97 while (node != null) { | 97 while (node !== null) { |
98 if (node.getAttribute('name') == name) { | 98 if (node.getAttribute('name') == name) { |
99 selected.push(node); | 99 selected.push(node); |
100 } | 100 } |
101 node = node.nextElementSibling; | 101 node = node.nextElementSibling; |
102 } | 102 } |
103 return selected; | 103 return selected; |
104 } | 104 }; |
105 } | 105 } |
106 | 106 |
107 var check_dependancies = function () { | 107 var check_dependancies = function () { |
108 // This will check for the data dependancies | 108 // This will check for the data dependancies |
109 if (typeof (jQuery) != "function") { | 109 if (typeof (jQuery) != "function") { |
120 } | 120 } |
121 if (typeof (validateXML) != "function") { | 121 if (typeof (validateXML) != "function") { |
122 return false; | 122 return false; |
123 } | 123 } |
124 return true; | 124 return true; |
125 } | 125 }; |
126 | 126 |
127 var onload = function () { | 127 var onload = function () { |
128 // Function called once the browser has loaded all files. | 128 // Function called once the browser has loaded all files. |
129 // This should perform any initial commands such as structure / loading documents | 129 // This should perform any initial commands such as structure / loading documents |
130 | 130 |
131 // Create a web audio API context | 131 // Create a web audio API context |
132 // Fixed for cross-browser support | 132 // Fixed for cross-browser support |
133 var AudioContext = window.AudioContext || window.webkitAudioContext; | 133 var AudioContext = window.AudioContext || window.webkitAudioContext; |
134 audioContext = new AudioContext; | 134 audioContext = new AudioContext(); |
135 | 135 |
136 // Create test state | 136 // Create test state |
137 testState = new stateMachine(); | 137 testState = new stateMachine(); |
138 | 138 |
139 // Create the popup interface object | 139 // Create the popup interface object |
150 // Define window callbacks for interface | 150 // Define window callbacks for interface |
151 window.onresize = function (event) { | 151 window.onresize = function (event) { |
152 interfaceContext.resizeWindow(event); | 152 interfaceContext.resizeWindow(event); |
153 }; | 153 }; |
154 | 154 |
155 if (window.location.search.length != 0) { | 155 if (window.location.search.length !== 0) { |
156 var search = window.location.search.split('?')[1]; | 156 var search = window.location.search.split('?')[1]; |
157 // Now split the requests into pairs | 157 // Now split the requests into pairs |
158 var searchQueries = search.split('&'); | 158 var searchQueries = search.split('&'); |
159 | 159 |
160 for (var i in searchQueries) { | 160 for (var i in searchQueries) { |
202 msg.textContent = "FATAL ERROR"; | 202 msg.textContent = "FATAL ERROR"; |
203 var span = document.createElement("p"); | 203 var span = document.createElement("p"); |
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."; | 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."; |
205 document.getElementsByTagName('body')[0].appendChild(msg); | 205 document.getElementsByTagName('body')[0].appendChild(msg); |
206 document.getElementsByTagName('body')[0].appendChild(span); | 206 document.getElementsByTagName('body')[0].appendChild(span); |
207 } | 207 }; |
208 r.send(); | 208 r.send(); |
209 }; | 209 }; |
210 xmlhttp.send(); | 210 xmlhttp.send(); |
211 }; | 211 } |
212 | 212 |
213 function loadProjectSpecCallback(response) { | 213 function loadProjectSpecCallback(response) { |
214 // Function called after asynchronous download of XML project specification | 214 // Function called after asynchronous download of XML project specification |
215 //var decode = $.parseXML(response); | 215 //var decode = $.parseXML(response); |
216 //projectXML = $(decode); | 216 //projectXML = $(decode); |
217 | 217 |
218 // Check if XML is new or a resumption | 218 // Check if XML is new or a resumption |
219 var parse = new DOMParser(); | 219 var parse = new DOMParser(); |
220 var responseDocument = parse.parseFromString(response, 'text/xml'); | 220 var responseDocument = parse.parseFromString(response, 'text/xml'); |
221 var errorNode = responseDocument.getElementsByTagName('parsererror'); | 221 var errorNode = responseDocument.getElementsByTagName('parsererror'); |
222 var msg, span; | |
222 if (errorNode.length >= 1) { | 223 if (errorNode.length >= 1) { |
223 var msg = document.createElement("h3"); | 224 msg = document.createElement("h3"); |
224 msg.textContent = "FATAL ERROR"; | 225 msg.textContent = "FATAL ERROR"; |
225 var span = document.createElement("span"); | 226 span = document.createElement("span"); |
226 span.textContent = "The XML parser returned the following errors when decoding your XML file"; | 227 span.textContent = "The XML parser returned the following errors when decoding your XML file"; |
227 document.getElementsByTagName('body')[0].innerHTML = null; | 228 document.getElementsByTagName('body')[0].innerHTML = null; |
228 document.getElementsByTagName('body')[0].appendChild(msg); | 229 document.getElementsByTagName('body')[0].appendChild(msg); |
229 document.getElementsByTagName('body')[0].appendChild(span); | 230 document.getElementsByTagName('body')[0].appendChild(span); |
230 document.getElementsByTagName('body')[0].appendChild(errorNode[0]); | 231 document.getElementsByTagName('body')[0].appendChild(errorNode[0]); |
231 return; | 232 return; |
232 } | 233 } |
233 if (responseDocument == undefined || responseDocument.firstChild == undefined) { | 234 if (responseDocument === undefined || responseDocument.firstChild === undefined) { |
234 var msg = document.createElement("h3"); | 235 msg = document.createElement("h3"); |
235 msg.textContent = "FATAL ERROR"; | 236 msg.textContent = "FATAL ERROR"; |
236 var span = document.createElement("span"); | 237 span = document.createElement("span"); |
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."; | 238 span.textContent = "The project XML was not decoded properly, try refreshing your browser and clearing caches. If the problem persists, contact the test creator."; |
238 document.getElementsByTagName('body')[0].innerHTML = null; | 239 document.getElementsByTagName('body')[0].innerHTML = null; |
239 document.getElementsByTagName('body')[0].appendChild(msg); | 240 document.getElementsByTagName('body')[0].appendChild(msg); |
240 document.getElementsByTagName('body')[0].appendChild(span); | 241 document.getElementsByTagName('body')[0].appendChild(span); |
241 return; | 242 return; |
252 projectXML = responseDocument; | 253 projectXML = responseDocument; |
253 var xmllint = validateXML(Module); | 254 var xmllint = validateXML(Module); |
254 console.log(xmllint); | 255 console.log(xmllint); |
255 if (xmllint != 'document.xml validates\n') { | 256 if (xmllint != 'document.xml validates\n') { |
256 document.getElementsByTagName('body')[0].innerHTML = null; | 257 document.getElementsByTagName('body')[0].innerHTML = null; |
257 var msg = document.createElement("h3"); | 258 msg = document.createElement("h3"); |
258 msg.textContent = "FATAL ERROR"; | 259 msg.textContent = "FATAL ERROR"; |
259 var span = document.createElement("h4"); | 260 span = document.createElement("h4"); |
260 span.textContent = "The XML validator returned the following errors when decoding your XML file"; | 261 span.textContent = "The XML validator returned the following errors when decoding your XML file"; |
261 document.getElementsByTagName('body')[0].appendChild(msg); | 262 document.getElementsByTagName('body')[0].appendChild(msg); |
262 document.getElementsByTagName('body')[0].appendChild(span); | 263 document.getElementsByTagName('body')[0].appendChild(span); |
263 xmllint = xmllint.split('\n'); | 264 xmllint = xmllint.split('\n'); |
264 for (var i in xmllint) { | 265 for (var i in xmllint) { |
265 document.getElementsByTagName('body')[0].appendChild(document.createElement('br')); | 266 document.getElementsByTagName('body')[0].appendChild(document.createElement('br')); |
266 var span = document.createElement("span"); | 267 span = document.createElement("span"); |
267 span.textContent = xmllint[i]; | 268 span.textContent = xmllint[i]; |
268 document.getElementsByTagName('body')[0].appendChild(span); | 269 document.getElementsByTagName('body')[0].appendChild(span); |
269 } | 270 } |
270 return; | 271 return; |
271 } | 272 } |
276 | 277 |
277 } else if (responseDocument.firstChild.nodeName == "waetresult") { | 278 } else if (responseDocument.firstChild.nodeName == "waetresult") { |
278 // document is a result | 279 // document is a result |
279 projectXML = document.implementation.createDocument(null, "waet"); | 280 projectXML = document.implementation.createDocument(null, "waet"); |
280 projectXML.firstChild.appendChild(responseDocument.getElementsByTagName('waet')[0].getElementsByTagName("setup")[0].cloneNode(true)); | 281 projectXML.firstChild.appendChild(responseDocument.getElementsByTagName('waet')[0].getElementsByTagName("setup")[0].cloneNode(true)); |
281 var child = responseDocument.firstChild.firstChild; | 282 var child = responseDocument.firstChild.firstChild, |
282 while (child != null) { | 283 copy; |
284 while (child !== null) { | |
283 if (child.nodeName == "survey") { | 285 if (child.nodeName == "survey") { |
284 // One of the global survey elements | 286 // One of the global survey elements |
285 if (child.getAttribute("state") == "complete") { | 287 if (child.getAttribute("state") == "complete") { |
286 // We need to remove this survey from <setup> | 288 // We need to remove this survey from <setup> |
287 var location = child.getAttribute("location"); | 289 var location = child.getAttribute("location"); |
288 var globalSurveys = projectXML.getElementsByTagName("setup")[0].getElementsByTagName("survey")[0]; | 290 var globalSurveys = projectXML.getElementsByTagName("setup")[0].getElementsByTagName("survey")[0]; |
289 while (globalSurveys != null) { | 291 while (globalSurveys !== null) { |
290 if (location == "pre" || location == "before") { | 292 if (location == "pre" || location == "before") { |
291 if (globalSurveys.getAttribute("location") == "pre" || globalSurveys.getAttribute("location") == "before") { | 293 if (globalSurveys.getAttribute("location") == "pre" || globalSurveys.getAttribute("location") == "before") { |
292 projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys); | 294 projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys); |
293 break; | 295 break; |
294 } | 296 } |
300 } | 302 } |
301 globalSurveys = globalSurveys.nextElementSibling; | 303 globalSurveys = globalSurveys.nextElementSibling; |
302 } | 304 } |
303 } else { | 305 } else { |
304 // We need to complete this, so it must be regenerated by store | 306 // We need to complete this, so it must be regenerated by store |
305 var copy = child; | 307 copy = child; |
306 child = child.previousElementSibling; | 308 child = child.previousElementSibling; |
307 responseDocument.firstChild.removeChild(copy); | 309 responseDocument.firstChild.removeChild(copy); |
308 } | 310 } |
309 } else if (child.nodeName == "page") { | 311 } else if (child.nodeName == "page") { |
310 if (child.getAttribute("state") == "empty") { | 312 if (child.getAttribute("state") == "empty") { |
311 // We need to complete this page | 313 // We need to complete this page |
312 projectXML.firstChild.appendChild(responseDocument.getElementById(child.getAttribute("ref")).cloneNode(true)); | 314 projectXML.firstChild.appendChild(responseDocument.getElementById(child.getAttribute("ref")).cloneNode(true)); |
313 var copy = child; | 315 copy = child; |
314 child = child.previousElementSibling; | 316 child = child.previousElementSibling; |
315 responseDocument.firstChild.removeChild(copy); | 317 responseDocument.firstChild.removeChild(copy); |
316 } | 318 } |
317 } | 319 } |
318 child = child.nextElementSibling; | 320 child = child.nextElementSibling; |
321 specification.decode(projectXML); | 323 specification.decode(projectXML); |
322 // Use the original | 324 // Use the original |
323 storage.initialise(responseDocument); | 325 storage.initialise(responseDocument); |
324 } | 326 } |
325 /// CHECK FOR SAMPLE RATE COMPATIBILITY | 327 /// CHECK FOR SAMPLE RATE COMPATIBILITY |
326 if (specification.sampleRate != undefined) { | 328 if (specification.sampleRate !== undefined) { |
327 if (Number(specification.sampleRate) != audioContext.sampleRate) { | 329 if (Number(specification.sampleRate) != audioContext.sampleRate) { |
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.'; | 330 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.'; |
329 interfaceContext.lightbox.post("Error", errStr); | 331 interfaceContext.lightbox.post("Error", errStr); |
330 return; | 332 return; |
331 } | 333 } |
333 | 335 |
334 var getInterfaces = new XMLHttpRequest(); | 336 var getInterfaces = new XMLHttpRequest(); |
335 getInterfaces.open("GET", "interfaces/interfaces.json"); | 337 getInterfaces.open("GET", "interfaces/interfaces.json"); |
336 getInterfaces.onerror = function (e) { | 338 getInterfaces.onerror = function (e) { |
337 throw (e); | 339 throw (e); |
338 } | 340 }; |
339 getInterfaces.onload = function () { | 341 getInterfaces.onload = function () { |
340 if (getInterfaces.status !== 200) { | 342 if (getInterfaces.status !== 200) { |
341 throw (new Error(getInterfaces.status)); | 343 throw (new Error(getInterfaces.status)); |
342 } | 344 } |
343 // Get the current interface | 345 // Get the current interface |
361 css.setAttribute("rel", "stylesheet"); | 363 css.setAttribute("rel", "stylesheet"); |
362 css.setAttribute("type", "text/css"); | 364 css.setAttribute("type", "text/css"); |
363 css.setAttribute("href", v); | 365 css.setAttribute("href", v); |
364 head.appendChild(css); | 366 head.appendChild(css); |
365 }); | 367 }); |
366 } | 368 }; |
367 getInterfaces.send(); | 369 getInterfaces.send(); |
368 | 370 |
369 if (gReturnURL != undefined) { | 371 if (gReturnURL !== undefined) { |
370 console.log("returnURL Overide from " + specification.returnURL + " to " + gReturnURL); | 372 console.log("returnURL Overide from " + specification.returnURL + " to " + gReturnURL); |
371 specification.returnURL = gReturnURL; | 373 specification.returnURL = gReturnURL; |
372 } | 374 } |
373 if (gSaveFilenamePrefix != undefined) { | 375 if (gSaveFilenamePrefix !== undefined) { |
374 specification.saveFilenamePrefix = gSaveFilenamePrefix; | 376 specification.saveFilenamePrefix = gSaveFilenamePrefix; |
375 } | 377 } |
376 | 378 |
377 // Create the audio engine object | 379 // Create the audio engine object |
378 audioEngineContext = new AudioEngine(specification); | 380 audioEngineContext = new AudioEngine(specification); |
413 if (specification.projectReturn.substr(0, 4) == "http") { | 415 if (specification.projectReturn.substr(0, 4) == "http") { |
414 projectReturn = specification.projectReturn; | 416 projectReturn = specification.projectReturn; |
415 } | 417 } |
416 } | 418 } |
417 var saveURL = projectReturn + "php/save.php?key=" + storage.SessionKey.key + saveUrlSuffix; | 419 var saveURL = projectReturn + "php/save.php?key=" + storage.SessionKey.key + saveUrlSuffix; |
418 var xmlhttp = new XMLHttpRequest; | 420 var xmlhttp = new XMLHttpRequest(); |
419 xmlhttp.open("POST", saveURL, true); | 421 xmlhttp.open("POST", saveURL, true); |
420 xmlhttp.setRequestHeader('Content-Type', 'text/xml'); | 422 xmlhttp.setRequestHeader('Content-Type', 'text/xml'); |
421 xmlhttp.onerror = function () { | 423 xmlhttp.onerror = function () { |
422 console.log('Error saving file to server! Presenting download locally'); | 424 console.log('Error saving file to server! Presenting download locally'); |
423 createProjectSave("local"); | 425 createProjectSave("local"); |
515 function samplesToSeconds(samples, fs) { | 517 function samplesToSeconds(samples, fs) { |
516 return samples / fs; | 518 return samples / fs; |
517 } | 519 } |
518 | 520 |
519 function randomString(length) { | 521 function randomString(length) { |
520 var str = "" | 522 var str = ""; |
521 for (var i = 0; i < length; i += 2) { | 523 for (var i = 0; i < length; i += 2) { |
522 var num = Math.floor(Math.random() * 1295); | 524 var num = Math.floor(Math.random() * 1295); |
523 str += num.toString(36); | 525 str += num.toString(36); |
524 } | 526 } |
525 return str; | 527 return str; |
530 // This takes an array of information and randomises the order | 532 // This takes an array of information and randomises the order |
531 var N = input.length; | 533 var N = input.length; |
532 | 534 |
533 var inputSequence = []; // For safety purposes: keep track of randomisation | 535 var inputSequence = []; // For safety purposes: keep track of randomisation |
534 for (var counter = 0; counter < N; ++counter) | 536 for (var counter = 0; counter < N; ++counter) |
535 inputSequence.push(counter) // Fill array | 537 inputSequence.push(counter); // Fill array |
536 var inputSequenceClone = inputSequence.slice(0); | 538 var inputSequenceClone = inputSequence.slice(0); |
537 | 539 |
538 var holdArr = []; | 540 var holdArr = []; |
539 var outputSequence = []; | 541 var outputSequence = []; |
540 for (var n = 0; n < N; n++) { | 542 for (var n = 0; n < N; n++) { |
582 console.log(e); | 584 console.log(e); |
583 popup.buttonProceed.onclick(); | 585 popup.buttonProceed.onclick(); |
584 e.preventDefault(); | 586 e.preventDefault(); |
585 } | 587 } |
586 }); | 588 }); |
589 // Generators & Processors // | |
590 | |
591 function processConditional(node, value) { | |
592 function jumpToId(jumpID) { | |
593 var index = this.popupOptions.findIndex(function (item, index, element) { | |
594 if (item.specification.id == jumpID) { | |
595 return true; | |
596 } else { | |
597 return false; | |
598 } | |
599 }, this); | |
600 this.currentIndex = index - 1; | |
601 } | |
602 var conditionFunction; | |
603 if (node.specification.type === "question") { | |
604 conditionFunction = processQuestionConditional; | |
605 } else if (node.specification.type === "checkbox") { | |
606 conditionFunction = processCheckboxConditional; | |
607 } else if (node.specification.type === "radio") { | |
608 conditionFunction = processRadioConditional; | |
609 } else if (node.specifiication.type === "number") { | |
610 conditionFunction = processNumberConditional; | |
611 } else if (node.specification.type === "slider") { | |
612 conditionFunction = processSliderConditional; | |
613 } else { | |
614 return; | |
615 } | |
616 for (var i = 0; i < node.specification.conditions; i++) { | |
617 var condition = node.specification.conditions[i]; | |
618 var pass = conditionFunction(condition, value); | |
619 var jumpID; | |
620 if (pass) { | |
621 jumpID = condition.jumpToOnPass; | |
622 } else { | |
623 jumpID = condition.jumpToOnFail; | |
624 } | |
625 if (jumpID !== undefined) { | |
626 jumpToId(jumpID); | |
627 break; | |
628 } | |
629 } | |
630 } | |
631 | |
632 function postQuestion(node) { | |
633 var textArea = document.createElement('textarea'); | |
634 switch (node.specification.boxsize) { | |
635 case 'small': | |
636 textArea.cols = "20"; | |
637 textArea.rows = "1"; | |
638 break; | |
639 case 'normal': | |
640 textArea.cols = "30"; | |
641 textArea.rows = "2"; | |
642 break; | |
643 case 'large': | |
644 textArea.cols = "40"; | |
645 textArea.rows = "5"; | |
646 break; | |
647 case 'huge': | |
648 textArea.cols = "50"; | |
649 textArea.rows = "10"; | |
650 break; | |
651 } | |
652 if (node.response === undefined) { | |
653 node.response = ""; | |
654 } else { | |
655 textArea.value = node.response; | |
656 } | |
657 this.popupResponse.appendChild(textArea); | |
658 textArea.focus(); | |
659 this.popupResponse.style.textAlign = "center"; | |
660 this.popupResponse.style.left = "0%"; | |
661 } | |
662 | |
663 function processQuestionConditional(condition, value) { | |
664 switch (condition.check) { | |
665 case "equals": | |
666 // Deliberately loose check | |
667 if (value == condition.value) { | |
668 return true; | |
669 } | |
670 break; | |
671 case "greaterThan": | |
672 case "lessThan": | |
673 console.log("Survey Element of type 'question' cannot interpret greaterThan/lessThan conditions. IGNORING"); | |
674 break; | |
675 case "contains": | |
676 if (textArea.value.includes(condition.value)) { | |
677 return true; | |
678 } | |
679 break; | |
680 } | |
681 return false; | |
682 } | |
683 | |
684 function processQuestion(node) { | |
685 var textArea = this.popupResponse.getAllElementsByTagName("textarea")[0]; | |
686 if (node.specification.mandatory === true && textArea.value.length === 0) { | |
687 interfaceContext.lightbox.post("Error", "This question is mandatory"); | |
688 return; | |
689 } else { | |
690 // Save the text content | |
691 console.log("Question: " + node.specification.statement); | |
692 console.log("Question Response: " + textArea.value); | |
693 node.response = textArea.value; | |
694 } | |
695 processConditional(node, textArea.value); | |
696 } | |
697 | |
698 function postCheckbox(node) { | |
699 if (node.response === undefined) { | |
700 node.response = Array(node.specification.options.length); | |
701 } | |
702 var index = 0; | |
703 var table = document.createElement("table"); | |
704 table.className = "popup-option-list"; | |
705 table.border = "0"; | |
706 node.specification.options.forEach(function (option) { | |
707 var tr = document.createElement("tr"); | |
708 table.appendChild(tr); | |
709 var td = document.createElement("td"); | |
710 tr.appendChild(td); | |
711 var input = document.createElement('input'); | |
712 input.id = option.name; | |
713 input.type = 'checkbox'; | |
714 td.appendChild(input); | |
715 | |
716 td = document.createElement("td"); | |
717 tr.appendChild(td); | |
718 var span = document.createElement('span'); | |
719 span.textContent = option.text; | |
720 td.appendChild(span); | |
721 tr = document.createElement('div'); | |
722 tr.setAttribute('name', 'option'); | |
723 tr.className = "popup-option-checbox"; | |
724 if (node.response[index] !== undefined) { | |
725 if (node.response[index].checked === true) { | |
726 input.checked = "true"; | |
727 } | |
728 } | |
729 index++; | |
730 }); | |
731 this.popupResponse.appendChild(table); | |
732 } | |
733 | |
734 function processCheckbox(node) { | |
735 console.log("Checkbox: " + node.specification.statement); | |
736 var inputs = this.popupResponse.getElementsByTagName('input'); | |
737 node.response = []; | |
738 var numChecked = 0, | |
739 i; | |
740 for (i = 0; i < node.specification.options.length; i++) { | |
741 if (inputs[i].checked) { | |
742 numChecked++; | |
743 } | |
744 } | |
745 if (node.specification.min !== undefined) { | |
746 if (node.specification.max === undefined) { | |
747 if (numChecked < node.specification.min) { | |
748 var msg = "You must select at least " + node.specification.min + " option"; | |
749 if (node.specification.min > 1) { | |
750 msg += "s"; | |
751 } | |
752 interfaceContext.lightbox.post("Error", msg); | |
753 return; | |
754 } | |
755 } else { | |
756 if (numChecked < node.specification.min || numChecked > node.specification.max) { | |
757 if (node.specification.min == node.specification.max) { | |
758 interfaceContext.lightbox.post("Error", "You must only select " + node.specification.min); | |
759 } else { | |
760 interfaceContext.lightbox.post("Error", "You must select between " + node.specification.min + " and " + node.specification.max); | |
761 } | |
762 return; | |
763 } | |
764 } | |
765 } | |
766 for (i = 0; i < node.specification.options.length; i++) { | |
767 node.response.push({ | |
768 name: node.specification.options[i].name, | |
769 text: node.specification.options[i].text, | |
770 checked: inputs[i].checked | |
771 }); | |
772 console.log(node.specification.options[i].name + ": " + inputs[i].checked); | |
773 } | |
774 processConditional(node, node.response); | |
775 } | |
776 | |
777 function processCheckboxConditional(condition, response) { | |
778 switch (condition.check) { | |
779 case "contains": | |
780 for (var i = 0; i < response.length; i++) { | |
781 var value = response[i]; | |
782 if (value.name === condition.value && value.checked) { | |
783 return true; | |
784 } | |
785 } | |
786 break; | |
787 case "equals": | |
788 case "greaterThan": | |
789 case "lessThan": | |
790 console.log("Survey Element of type 'checkbox' cannot interpret equals/greaterThan/lessThan conditions. IGNORING"); | |
791 break; | |
792 default: | |
793 console.log("Unknown condition. IGNORING"); | |
794 break; | |
795 } | |
796 return false; | |
797 } | |
798 | |
799 function postRadio(node) { | |
800 if (node.response === undefined) { | |
801 node.response = { | |
802 name: "", | |
803 text: "" | |
804 }; | |
805 } | |
806 var index = 0; | |
807 var table = document.createElement("table"); | |
808 table.className = "popup-option-list"; | |
809 table.border = "0"; | |
810 node.specification.options.forEach(function (option) { | |
811 var tr = document.createElement("tr"); | |
812 table.appendChild(tr); | |
813 var td = document.createElement("td"); | |
814 tr.appendChild(td); | |
815 var input = document.createElement('input'); | |
816 input.id = option.name; | |
817 input.type = 'radio'; | |
818 input.name = node.specification.id; | |
819 td.appendChild(input); | |
820 | |
821 td = document.createElement("td"); | |
822 tr.appendChild(td); | |
823 var span = document.createElement('span'); | |
824 span.textContent = option.text; | |
825 td.appendChild(span); | |
826 tr = document.createElement('div'); | |
827 tr.setAttribute('name', 'option'); | |
828 tr.className = "popup-option-checbox"; | |
829 if (node.response[index] !== undefined) { | |
830 if (node.response[index].checked === true) { | |
831 input.checked = "true"; | |
832 } | |
833 } | |
834 index++; | |
835 }); | |
836 this.popupResponse.appendChild(table); | |
837 } | |
838 | |
839 function processRadio(node) { | |
840 var optHold = this.popupResponse; | |
841 console.log("Radio: " + node.specification.statement); | |
842 node.response = null; | |
843 var i = 0; | |
844 var inputs = optHold.getElementsByTagName('input'); | |
845 while (node.response === null) { | |
846 if (i == inputs.length) { | |
847 if (node.specification.mandatory === true) { | |
848 interfaceContext.lightbox.post("Error", "Please select one option"); | |
849 return; | |
850 } | |
851 break; | |
852 } | |
853 if (inputs[i].checked === true) { | |
854 node.response = node.specification.options[i]; | |
855 console.log("Selected: " + node.specification.options[i].name); | |
856 } | |
857 i++; | |
858 } | |
859 processConditional(node, node.response); | |
860 } | |
861 | |
862 function processRadioConditional(condition, response) { | |
863 switch (condition.check) { | |
864 case "equals": | |
865 if (node.response === condition.value) { | |
866 return true; | |
867 } | |
868 break; | |
869 case "contains": | |
870 case "greaterThan": | |
871 case "lessThan": | |
872 console.log("Survey Element of type 'radio' cannot interpret contains/greaterThan/lessThan conditions. IGNORING"); | |
873 break; | |
874 default: | |
875 console.log("Unknown condition. IGNORING"); | |
876 break; | |
877 } | |
878 return false; | |
879 } | |
880 | |
881 function postNumber(node) { | |
882 var input = document.createElement('input'); | |
883 input.type = 'textarea'; | |
884 if (node.specification.min !== null) { | |
885 input.min = node.specification.min; | |
886 } | |
887 if (node.specification.max !== null) { | |
888 input.max = node.specification.max; | |
889 } | |
890 if (node.specification.step !== null) { | |
891 input.step = node.specification.step; | |
892 } | |
893 if (node.response !== undefined) { | |
894 input.value = node.response; | |
895 } | |
896 this.popupResponse.appendChild(input); | |
897 this.popupResponse.style.textAlign = "center"; | |
898 this.popupResponse.style.left = "0%"; | |
899 } | |
900 | |
901 function processNumber(node) { | |
902 var input = this.popupContent.getElementsByTagName('input')[0]; | |
903 if (node.mandatory === true && input.value.length === 0) { | |
904 interfaceContext.lightbox.post("Error", 'This question is mandatory. Please enter a number'); | |
905 return; | |
906 } | |
907 var enteredNumber = Number(input.value); | |
908 if (isNaN(enteredNumber)) { | |
909 interfaceContext.lightbox.post("Error", 'Please enter a valid number'); | |
910 return; | |
911 } | |
912 if (enteredNumber < node.min && node.min !== null) { | |
913 interfaceContext.lightbox.post("Error", 'Number is below the minimum value of ' + node.min); | |
914 return; | |
915 } | |
916 if (enteredNumber > node.max && node.max !== null) { | |
917 interfaceContext.lightbox.post("Error", 'Number is above the maximum value of ' + node.max); | |
918 return; | |
919 } | |
920 node.response = input.value; | |
921 } | |
922 | |
923 function processNumberConditional(condtion, value) { | |
924 switch (condition.check) { | |
925 case "greaterThan": | |
926 if (node.response > Number(condition.value)) { | |
927 return true; | |
928 } | |
929 break; | |
930 case "lessThan": | |
931 if (node.response < Number(condition.value)) { | |
932 return true; | |
933 } | |
934 break; | |
935 case "equals": | |
936 if (node.response == condition.value) { | |
937 return true; | |
938 } | |
939 break; | |
940 case "contains": | |
941 console.log("Survey Element of type 'number' cannot interpret \"contains\" conditions. IGNORING"); | |
942 break; | |
943 default: | |
944 console.log("Unknown condition. IGNORING"); | |
945 break; | |
946 } | |
947 return false; | |
948 } | |
949 | |
950 function postVideo(node) { | |
951 var video = document.createElement("video"); | |
952 video.src = node.specification.url; | |
953 this.popupResponse.appendChild(video); | |
954 } | |
955 | |
956 function postYoutube(node) { | |
957 var iframe = document.createElement("iframe"); | |
958 iframe.className = "youtube"; | |
959 iframe.src = node.specification.url; | |
960 this.popupResponse.appendChild(iframe); | |
961 } | |
962 | |
963 function postSlider(node) { | |
964 var hold = document.createElement('div'); | |
965 var input = document.createElement('input'); | |
966 input.type = 'range'; | |
967 input.style.width = "90%"; | |
968 if (node.specification.min !== null) { | |
969 input.min = node.specification.min; | |
970 } | |
971 if (node.specification.max !== null) { | |
972 input.max = node.specification.max; | |
973 } | |
974 if (node.response !== undefined) { | |
975 input.value = node.response; | |
976 } | |
977 hold.className = "survey-slider-text-holder"; | |
978 var minText = document.createElement('span'); | |
979 var maxText = document.createElement('span'); | |
980 minText.textContent = node.specification.leftText; | |
981 maxText.textContent = node.specification.rightText; | |
982 hold.appendChild(minText); | |
983 hold.appendChild(maxText); | |
984 this.popupResponse.appendChild(input); | |
985 this.popupResponse.appendChild(hold); | |
986 this.popupResponse.style.textAlign = "center"; | |
987 } | |
988 | |
989 function processSlider(node) { | |
990 var input = this.popupContent.getElementsByTagName('input')[0]; | |
991 node.response = input.value; | |
992 } | |
993 | |
994 function processSliderConditional(condition, value) { | |
995 switch (condition.check) { | |
996 case "contains": | |
997 console.log("Survey Element of type 'number' cannot interpret contains conditions. IGNORING"); | |
998 break; | |
999 case "greaterThan": | |
1000 if (node.response > Number(condition.value)) { | |
1001 return true; | |
1002 } | |
1003 break; | |
1004 case "lessThan": | |
1005 if (node.response < Number(condition.value)) { | |
1006 return true; | |
1007 } | |
1008 break; | |
1009 case "equals": | |
1010 if (node.response == condition.value) { | |
1011 return true; | |
1012 } | |
1013 break; | |
1014 default: | |
1015 console.log("Unknown condition. IGNORING"); | |
1016 break; | |
1017 } | |
1018 return false; | |
1019 } | |
587 | 1020 |
588 this.createPopup = function () { | 1021 this.createPopup = function () { |
589 // Create popup window interface | 1022 // Create popup window interface |
590 var insertPoint = document.getElementById("topLevelBody"); | 1023 var insertPoint = document.getElementById("topLevelBody"); |
591 | 1024 |
612 this.hidePopup(); | 1045 this.hidePopup(); |
613 this.popup.style.visibility = 'hidden'; | 1046 this.popup.style.visibility = 'hidden'; |
614 }; | 1047 }; |
615 | 1048 |
616 this.showPopup = function () { | 1049 this.showPopup = function () { |
617 if (this.popup == null) { | 1050 if (this.popup === null) { |
618 this.createPopup(); | 1051 this.createPopup(); |
619 } | 1052 } |
620 this.popup.style.visibility = 'visible'; | 1053 this.popup.style.visibility = 'visible'; |
621 var blank = document.getElementsByClassName('testHalt')[0]; | 1054 var blank = document.getElementsByClassName('testHalt')[0]; |
622 blank.style.visibility = 'visible'; | 1055 blank.style.visibility = 'visible'; |
639 p = new DOMParser(); | 1072 p = new DOMParser(); |
640 this.popupResponse.innerHTML = ""; | 1073 this.popupResponse.innerHTML = ""; |
641 this.popupTitle.innerHTML = ""; | 1074 this.popupTitle.innerHTML = ""; |
642 this.popupTitle.appendChild(p.parseFromString(converter.makeHtml(node.specification.statement), "text/html").getElementsByTagName("body")[0].firstElementChild); | 1075 this.popupTitle.appendChild(p.parseFromString(converter.makeHtml(node.specification.statement), "text/html").getElementsByTagName("body")[0].firstElementChild); |
643 if (node.specification.type == 'question') { | 1076 if (node.specification.type == 'question') { |
644 var textArea = document.createElement('textarea'); | 1077 postQuestion(node); |
645 switch (node.specification.boxsize) { | |
646 case 'small': | |
647 textArea.cols = "20"; | |
648 textArea.rows = "1"; | |
649 break; | |
650 case 'normal': | |
651 textArea.cols = "30"; | |
652 textArea.rows = "2"; | |
653 break; | |
654 case 'large': | |
655 textArea.cols = "40"; | |
656 textArea.rows = "5"; | |
657 break; | |
658 case 'huge': | |
659 textArea.cols = "50"; | |
660 textArea.rows = "10"; | |
661 break; | |
662 } | |
663 if (node.response == undefined) { | |
664 node.response = ""; | |
665 } else { | |
666 textArea.value = node.response; | |
667 } | |
668 this.popupResponse.appendChild(textArea); | |
669 textArea.focus(); | |
670 this.popupResponse.style.textAlign = "center"; | |
671 this.popupResponse.style.left = "0%"; | |
672 } else if (node.specification.type == 'checkbox') { | 1078 } else if (node.specification.type == 'checkbox') { |
673 if (node.response == undefined) { | 1079 postCheckbox(node); |
674 node.response = Array(node.specification.options.length); | |
675 } | |
676 var index = 0; | |
677 var table = document.createElement("table"); | |
678 table.className = "popup-option-list"; | |
679 table.border = "0"; | |
680 for (var option of node.specification.options) { | |
681 var tr = document.createElement("tr"); | |
682 table.appendChild(tr); | |
683 var td = document.createElement("td"); | |
684 tr.appendChild(td); | |
685 var input = document.createElement('input'); | |
686 input.id = option.name; | |
687 input.type = 'checkbox'; | |
688 td.appendChild(input); | |
689 | |
690 td = document.createElement("td"); | |
691 tr.appendChild(td); | |
692 var span = document.createElement('span'); | |
693 span.textContent = option.text; | |
694 td.appendChild(span); | |
695 var tr = document.createElement('div'); | |
696 tr.setAttribute('name', 'option'); | |
697 tr.className = "popup-option-checbox"; | |
698 if (node.response[index] != undefined) { | |
699 if (node.response[index].checked == true) { | |
700 input.checked = "true"; | |
701 } | |
702 } | |
703 index++; | |
704 } | |
705 this.popupResponse.appendChild(table); | |
706 } else if (node.specification.type == 'radio') { | 1080 } else if (node.specification.type == 'radio') { |
707 if (node.response == undefined) { | 1081 postRadio(node); |
708 node.response = { | |
709 name: "", | |
710 text: "" | |
711 }; | |
712 } | |
713 var index = 0; | |
714 var table = document.createElement("table"); | |
715 table.className = "popup-option-list"; | |
716 table.border = "0"; | |
717 for (var option of node.specification.options) { | |
718 var tr = document.createElement("tr"); | |
719 table.appendChild(tr); | |
720 var td = document.createElement("td"); | |
721 tr.appendChild(td); | |
722 var input = document.createElement('input'); | |
723 input.id = option.name; | |
724 input.type = 'radio'; | |
725 input.name = node.specification.id; | |
726 td.appendChild(input); | |
727 | |
728 td = document.createElement("td"); | |
729 tr.appendChild(td); | |
730 var span = document.createElement('span'); | |
731 span.textContent = option.text; | |
732 td.appendChild(span); | |
733 var tr = document.createElement('div'); | |
734 tr.setAttribute('name', 'option'); | |
735 tr.className = "popup-option-checbox"; | |
736 if (node.response[index] != undefined) { | |
737 if (node.response[index].checked == true) { | |
738 input.checked = "true"; | |
739 } | |
740 } | |
741 index++; | |
742 } | |
743 this.popupResponse.appendChild(table); | |
744 } else if (node.specification.type == 'number') { | 1082 } else if (node.specification.type == 'number') { |
745 var input = document.createElement('input'); | 1083 postNumber(node); |
746 input.type = 'textarea'; | |
747 if (node.specification.min != null) { | |
748 input.min = node.specification.min; | |
749 } | |
750 if (node.specification.max != null) { | |
751 input.max = node.specification.max; | |
752 } | |
753 if (node.specification.step != null) { | |
754 input.step = node.specification.step; | |
755 } | |
756 if (node.response != undefined) { | |
757 input.value = node.response; | |
758 } | |
759 this.popupResponse.appendChild(input); | |
760 this.popupResponse.style.textAlign = "center"; | |
761 this.popupResponse.style.left = "0%"; | |
762 } else if (node.specification.type == "video") { | 1084 } else if (node.specification.type == "video") { |
763 var video = document.createElement("video"); | 1085 postVideo(node); |
764 video.src = node.specification.url; | |
765 this.popupResponse.appendChild(video); | |
766 } else if (node.specification.type == "youtube") { | 1086 } else if (node.specification.type == "youtube") { |
767 var iframe = document.createElement("iframe"); | 1087 postYoutube(node); |
768 iframe.className = "youtube"; | |
769 iframe.src = node.specification.url; | |
770 this.popupResponse.appendChild(iframe); | |
771 } else if (node.specification.type == "slider") { | 1088 } else if (node.specification.type == "slider") { |
772 var hold = document.createElement('div'); | 1089 postSlider(node); |
773 var input = document.createElement('input'); | |
774 input.type = 'range'; | |
775 input.style.width = "90%"; | |
776 if (node.specification.min != null) { | |
777 input.min = node.specification.min; | |
778 } | |
779 if (node.specification.max != null) { | |
780 input.max = node.specification.max; | |
781 } | |
782 if (node.response != undefined) { | |
783 input.value = node.response; | |
784 } | |
785 hold.className = "survey-slider-text-holder"; | |
786 var minText = document.createElement('span'); | |
787 var maxText = document.createElement('span'); | |
788 minText.textContent = node.specification.leftText; | |
789 maxText.textContent = node.specification.rightText; | |
790 hold.appendChild(minText); | |
791 hold.appendChild(maxText); | |
792 this.popupResponse.appendChild(input); | |
793 this.popupResponse.appendChild(hold); | |
794 this.popupResponse.style.textAlign = "center"; | |
795 } | 1090 } |
796 if (this.currentIndex + 1 == this.popupOptions.length) { | 1091 if (this.currentIndex + 1 == this.popupOptions.length) { |
797 if (this.node.location == "pre") { | 1092 if (this.node.location == "pre") { |
798 this.buttonProceed.textContent = 'Start'; | 1093 this.buttonProceed.textContent = 'Start'; |
799 } else { | 1094 } else { |
813 // initialise the popup procedure. | 1108 // initialise the popup procedure. |
814 if (node.options.length > 0) { | 1109 if (node.options.length > 0) { |
815 this.popupOptions = []; | 1110 this.popupOptions = []; |
816 this.node = node; | 1111 this.node = node; |
817 this.store = store; | 1112 this.store = store; |
818 for (var opt of node.options) { | 1113 node.options.forEach(function (opt) { |
819 this.popupOptions.push({ | 1114 this.popupOptions.push({ |
820 specification: opt, | 1115 specification: opt, |
821 response: null | 1116 response: null |
822 }); | 1117 }); |
823 } | 1118 }, this); |
824 this.currentIndex = 0; | 1119 this.currentIndex = 0; |
825 this.showPopup(); | 1120 this.showPopup(); |
826 this.postNode(); | 1121 this.postNode(); |
827 } else { | 1122 } else { |
828 advanceState(); | 1123 advanceState(); |
829 } | 1124 } |
830 }; | 1125 }; |
831 | 1126 |
832 this.proceedClicked = function () { | 1127 this.proceedClicked = function () { |
833 // Each time the popup button is clicked! | 1128 // Each time the popup button is clicked! |
834 if (testState.stateIndex == 0 && specification.calibration) { | 1129 if (testState.stateIndex === 0 && specification.calibration) { |
835 interfaceContext.calibrationModuleObject.collect(); | 1130 interfaceContext.calibrationModuleObject.collect(); |
836 advanceState(); | 1131 advanceState(); |
837 return; | 1132 return; |
838 } | 1133 } |
839 var node = this.popupOptions[this.currentIndex]; | 1134 var node = this.popupOptions[this.currentIndex]; |
840 if (node.specification.type == 'question') { | 1135 if (node.specification.type == 'question') { |
841 // Must extract the question data | 1136 // Must extract the question data |
842 var textArea = $(popup.popupContent).find('textarea')[0]; | 1137 processQuestion(node); |
843 if (node.specification.mandatory == true && textArea.value.length == 0) { | |
844 interfaceContext.lightbox.post("Error", "This question is mandatory"); | |
845 return; | |
846 } else { | |
847 // Save the text content | |
848 console.log("Question: " + node.specification.statement); | |
849 console.log("Question Response: " + textArea.value); | |
850 node.response = textArea.value; | |
851 } | |
852 // Perform the conditional | |
853 for (var condition of node.specification.conditions) { | |
854 var pass = false; | |
855 switch (condition.check) { | |
856 case "equals": | |
857 if (textArea.value == condition.value) { | |
858 pass = true; | |
859 } | |
860 break; | |
861 case "greaterThan": | |
862 case "lessThan": | |
863 console.log("Survey Element of type 'question' cannot interpret greaterThan/lessThan conditions. IGNORING"); | |
864 break; | |
865 case "contains": | |
866 if (textArea.value.includes(condition.value)) { | |
867 pass = true; | |
868 } | |
869 break; | |
870 } | |
871 var jumpID; | |
872 if (pass) { | |
873 jumpID = condition.jumpToOnPass; | |
874 } else { | |
875 jumpID = condition.jumpToOnFail; | |
876 } | |
877 if (jumpID != undefined) { | |
878 var index = this.popupOptions.findIndex(function (item, index, element) { | |
879 if (item.specification.id == jumpID) { | |
880 return true; | |
881 } else { | |
882 return false; | |
883 } | |
884 }, this); | |
885 this.currentIndex = index - 1; | |
886 break; | |
887 } | |
888 } | |
889 } else if (node.specification.type == 'checkbox') { | 1138 } else if (node.specification.type == 'checkbox') { |
890 // Must extract checkbox data | 1139 // Must extract checkbox data |
891 console.log("Checkbox: " + node.specification.statement); | 1140 processCheckbox(node); |
892 var inputs = this.popupResponse.getElementsByTagName('input'); | 1141 } else if (node.specification.type == "radio") { |
893 node.response = []; | |
894 var numChecked = 0; | |
895 for (var i = 0; i < node.specification.options.length; i++) { | |
896 if (inputs[i].checked) { | |
897 numChecked++; | |
898 } | |
899 } | |
900 if (node.specification.min != undefined) { | |
901 if (node.specification.max == undefined) { | |
902 if (numChecked < node.specification.min) { | |
903 var msg = "You must select at least " + node.specification.min + " option"; | |
904 if (node.specification.min > 1) { | |
905 msg += "s"; | |
906 } | |
907 interfaceContext.lightbox.post("Error", msg); | |
908 return; | |
909 } | |
910 } else { | |
911 if (numChecked < node.specification.min || numChecked > node.specification.max) { | |
912 if (node.specification.min == node.specification.max) { | |
913 interfaceContext.lightbox.post("Error", "You must only select " + node.specification.min); | |
914 } else { | |
915 interfaceContext.lightbox.post("Error", "You must select between " + node.specification.min + " and " + node.specification.max); | |
916 } | |
917 return; | |
918 } | |
919 } | |
920 } | |
921 for (var i = 0; i < node.specification.options.length; i++) { | |
922 node.response.push({ | |
923 name: node.specification.options[i].name, | |
924 text: node.specification.options[i].text, | |
925 checked: inputs[i].checked | |
926 }); | |
927 console.log(node.specification.options[i].name + ": " + inputs[i].checked); | |
928 } | |
929 // Perform the conditional | 1142 // Perform the conditional |
930 for (var condition of node.specification.conditions) { | 1143 processRadio(node); |
931 var pass = false; | 1144 } else if (node.specification.type == "number") { |
932 switch (condition.check) { | |
933 case "equals": | |
934 case "greaterThan": | |
935 case "lessThan": | |
936 console.log("Survey Element of type 'checkbox' cannot interpret equals/greaterThan/lessThan conditions. IGNORING"); | |
937 break; | |
938 case "contains": | |
939 for (var response of node.response) { | |
940 if (response.name == condition.value && response.checked) { | |
941 pass = true; | |
942 break; | |
943 } | |
944 } | |
945 break; | |
946 } | |
947 var jumpID; | |
948 if (pass) { | |
949 jumpID = condition.jumpToOnPass; | |
950 } else { | |
951 jumpID = condition.jumpToOnFail; | |
952 } | |
953 if (jumpID != undefined) { | |
954 var index = this.popupOptions.findIndex(function (item, index, element) { | |
955 if (item.specification.id == jumpID) { | |
956 return true; | |
957 } else { | |
958 return false; | |
959 } | |
960 }, this); | |
961 this.currentIndex = index - 1; | |
962 break; | |
963 } | |
964 } | |
965 } else if (node.specification.type == "radio") { | |
966 var optHold = this.popupResponse; | |
967 console.log("Radio: " + node.specification.statement); | |
968 node.response = null; | |
969 var i = 0; | |
970 var inputs = optHold.getElementsByTagName('input'); | |
971 while (node.response == null) { | |
972 if (i == inputs.length) { | |
973 if (node.specification.mandatory == true) { | |
974 interfaceContext.lightbox.post("Error", "Please select one option"); | |
975 return; | |
976 } | |
977 break; | |
978 } | |
979 if (inputs[i].checked == true) { | |
980 node.response = node.specification.options[i]; | |
981 console.log("Selected: " + node.specification.options[i].name); | |
982 } | |
983 i++; | |
984 } | |
985 // Perform the conditional | 1145 // Perform the conditional |
986 for (var condition of node.specification.conditions) { | 1146 processNumber(node); |
987 var pass = false; | |
988 switch (condition.check) { | |
989 case "contains": | |
990 case "greaterThan": | |
991 case "lessThan": | |
992 console.log("Survey Element of type 'radio' cannot interpret contains/greaterThan/lessThan conditions. IGNORING"); | |
993 break; | |
994 case "equals": | |
995 if (node.response == condition.value) { | |
996 pass = true; | |
997 } | |
998 break; | |
999 } | |
1000 var jumpID; | |
1001 if (pass) { | |
1002 jumpID = condition.jumpToOnPass; | |
1003 } else { | |
1004 jumpID = condition.jumpToOnFail; | |
1005 } | |
1006 if (jumpID != undefined) { | |
1007 var index = this.popupOptions.findIndex(function (item, index, element) { | |
1008 if (item.specification.id == jumpID) { | |
1009 return true; | |
1010 } else { | |
1011 return false; | |
1012 } | |
1013 }, this); | |
1014 this.currentIndex = index - 1; | |
1015 break; | |
1016 } | |
1017 } | |
1018 } else if (node.specification.type == "number") { | |
1019 var input = this.popupContent.getElementsByTagName('input')[0]; | |
1020 if (node.mandatory == true && input.value.length == 0) { | |
1021 interfaceContext.lightbox.post("Error", 'This question is mandatory. Please enter a number'); | |
1022 return; | |
1023 } | |
1024 var enteredNumber = Number(input.value); | |
1025 if (isNaN(enteredNumber)) { | |
1026 interfaceContext.lightbox.post("Error", 'Please enter a valid number'); | |
1027 return; | |
1028 } | |
1029 if (enteredNumber < node.min && node.min != null) { | |
1030 interfaceContext.lightbox.post("Error", 'Number is below the minimum value of ' + node.min); | |
1031 return; | |
1032 } | |
1033 if (enteredNumber > node.max && node.max != null) { | |
1034 interfaceContext.lightbox.post("Error", 'Number is above the maximum value of ' + node.max); | |
1035 return; | |
1036 } | |
1037 node.response = input.value; | |
1038 // Perform the conditional | |
1039 for (var condition of node.specification.conditions) { | |
1040 var pass = false; | |
1041 switch (condition.check) { | |
1042 case "contains": | |
1043 console.log("Survey Element of type 'number' cannot interpret contains conditions. IGNORING"); | |
1044 break; | |
1045 case "greaterThan": | |
1046 if (node.response > Number(condition.value)) { | |
1047 pass = true; | |
1048 } | |
1049 break; | |
1050 case "lessThan": | |
1051 if (node.response < Number(condition.value)) { | |
1052 pass = true; | |
1053 } | |
1054 break; | |
1055 case "equals": | |
1056 if (node.response == condition.value) { | |
1057 pass = true; | |
1058 } | |
1059 break; | |
1060 } | |
1061 var jumpID; | |
1062 if (pass) { | |
1063 jumpID = condition.jumpToOnPass; | |
1064 } else { | |
1065 jumpID = condition.jumpToOnFail; | |
1066 } | |
1067 if (jumpID != undefined) { | |
1068 var index = this.popupOptions.findIndex(function (item, index, element) { | |
1069 if (item.specification.id == jumpID) { | |
1070 return true; | |
1071 } else { | |
1072 return false; | |
1073 } | |
1074 }, this); | |
1075 this.currentIndex = index - 1; | |
1076 break; | |
1077 } | |
1078 } | |
1079 } else if (node.specification.type == 'slider') { | 1147 } else if (node.specification.type == 'slider') { |
1080 var input = this.popupContent.getElementsByTagName('input')[0]; | 1148 processSlider(node); |
1081 node.response = input.value; | |
1082 for (var condition of node.specification.conditions) { | |
1083 var pass = false; | |
1084 switch (condition.check) { | |
1085 case "contains": | |
1086 console.log("Survey Element of type 'number' cannot interpret contains conditions. IGNORING"); | |
1087 break; | |
1088 case "greaterThan": | |
1089 if (node.response > Number(condition.value)) { | |
1090 pass = true; | |
1091 } | |
1092 break; | |
1093 case "lessThan": | |
1094 if (node.response < Number(condition.value)) { | |
1095 pass = true; | |
1096 } | |
1097 break; | |
1098 case "equals": | |
1099 if (node.response == condition.value) { | |
1100 pass = true; | |
1101 } | |
1102 break; | |
1103 } | |
1104 var jumpID; | |
1105 if (pass) { | |
1106 jumpID = condition.jumpToOnPass; | |
1107 } else { | |
1108 jumpID = condition.jumpToOnFail; | |
1109 } | |
1110 if (jumpID != undefined) { | |
1111 var index = this.popupOptions.findIndex(function (item, index, element) { | |
1112 if (item.specification.id == jumpID) { | |
1113 return true; | |
1114 } else { | |
1115 return false; | |
1116 } | |
1117 }, this); | |
1118 this.currentIndex = index - 1; | |
1119 break; | |
1120 } | |
1121 } | |
1122 } | 1149 } |
1123 this.currentIndex++; | 1150 this.currentIndex++; |
1124 if (this.currentIndex < this.popupOptions.length) { | 1151 if (this.currentIndex < this.popupOptions.length) { |
1125 this.postNode(); | 1152 this.postNode(); |
1126 } else { | 1153 } else { |
1127 // Reached the end of the popupOptions | 1154 // Reached the end of the popupOptions |
1128 this.popupTitle.innerHTML = ""; | 1155 this.popupTitle.innerHTML = ""; |
1129 this.popupResponse.innerHTML = ""; | 1156 this.popupResponse.innerHTML = ""; |
1130 this.hidePopup(); | 1157 this.hidePopup(); |
1131 for (var node of this.popupOptions) { | 1158 this.popupOptions.forEach(function (node) { |
1132 this.store.postResult(node); | 1159 this.store.postResult(node); |
1133 } | 1160 }, this); |
1134 this.store.complete(); | 1161 this.store.complete(); |
1135 advanceState(); | 1162 advanceState(); |
1136 } | 1163 } |
1137 }; | 1164 }; |
1138 | 1165 |
1144 } | 1171 } |
1145 }; | 1172 }; |
1146 | 1173 |
1147 this.resize = function (event) { | 1174 this.resize = function (event) { |
1148 // Called on window resize; | 1175 // Called on window resize; |
1149 if (this.popup != null) { | 1176 if (this.popup !== null) { |
1150 this.popup.style.left = (window.innerWidth / 2) - 250 + 'px'; | 1177 this.popup.style.left = (window.innerWidth / 2) - 250 + 'px'; |
1151 this.popup.style.top = (window.innerHeight / 2) - 125 + 'px'; | 1178 this.popup.style.top = (window.innerHeight / 2) - 125 + 'px'; |
1152 var blank = document.getElementsByClassName('testHalt')[0]; | 1179 var blank = document.getElementsByClassName('testHalt')[0]; |
1153 blank.style.width = window.innerWidth; | 1180 blank.style.width = window.innerWidth; |
1154 blank.style.height = window.innerHeight; | 1181 blank.style.height = window.innerHeight; |
1155 } | 1182 } |
1156 }; | 1183 }; |
1157 this.hideNextButton = function () { | 1184 this.hideNextButton = function () { |
1158 this.buttonProceed.style.visibility = "hidden"; | 1185 this.buttonProceed.style.visibility = "hidden"; |
1159 } | 1186 }; |
1160 this.hidePreviousButton = function () { | 1187 this.hidePreviousButton = function () { |
1161 this.buttonPrevious.style.visibility = "hidden"; | 1188 this.buttonPrevious.style.visibility = "hidden"; |
1162 } | 1189 }; |
1163 this.showNextButton = function () { | 1190 this.showNextButton = function () { |
1164 this.buttonProceed.style.visibility = "visible"; | 1191 this.buttonProceed.style.visibility = "visible"; |
1165 } | 1192 }; |
1166 this.showPreviousButton = function () { | 1193 this.showPreviousButton = function () { |
1167 this.buttonPrevious.style.visibility = "visible"; | 1194 this.buttonPrevious.style.visibility = "visible"; |
1168 } | 1195 }; |
1169 } | 1196 } |
1170 | 1197 |
1171 function advanceState() { | 1198 function advanceState() { |
1172 // Just for complete clarity | 1199 // Just for complete clarity |
1173 testState.advanceState(); | 1200 testState.advanceState(); |