comparison core.js @ 1581:284251e3a6a3

Everything tied into Specification object which needs information from specification document.
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Thu, 04 Jun 2015 15:54:56 +0100
parents b6c808cac38c
children b84004661558
comparison
equal deleted inserted replaced
1580:b6c808cac38c 1581:284251e3a6a3
6 */ 6 */
7 7
8 /* create the web audio API context and store in audioContext*/ 8 /* create the web audio API context and store in audioContext*/
9 var audioContext; // Hold the browser web audio API 9 var audioContext; // Hold the browser web audio API
10 var projectXML; // Hold the parsed setup XML 10 var projectXML; // Hold the parsed setup XML
11 var specification;
11 var popup; // Hold the interfacePopup object 12 var popup; // Hold the interfacePopup object
12 var testState; 13 var testState;
13 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order 14 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order
14 var audioEngineContext; // The custome AudioEngine object 15 var audioEngineContext; // The custome AudioEngine object
15 var projectReturn; // Hold the URL for the return 16 var projectReturn; // Hold the URL for the return
33 // Create the audio engine object 34 // Create the audio engine object
34 audioEngineContext = new AudioEngine(); 35 audioEngineContext = new AudioEngine();
35 36
36 // Create the popup interface object 37 // Create the popup interface object
37 popup = new interfacePopup(); 38 popup = new interfacePopup();
39
40 // Create the specification object
41 specification = new Specification();
38 }; 42 };
39 43
40 function interfacePopup() { 44 function interfacePopup() {
41 // Creates an object to manage the popup 45 // Creates an object to manage the popup
42 this.popup = null; 46 this.popup = null;
43 this.popupContent = null; 47 this.popupContent = null;
44 this.popupButton = null; 48 this.popupButton = null;
45 this.popupOptions = null; 49 this.popupOptions = null;
46 this.currentIndex = null; 50 this.currentIndex = null;
47 this.responses = null; 51 this.responses = null;
52
48 this.createPopup = function(){ 53 this.createPopup = function(){
49 // Create popup window interface 54 // Create popup window interface
50 var insertPoint = document.getElementById("topLevelBody"); 55 var insertPoint = document.getElementById("topLevelBody");
51 var blank = document.createElement('div'); 56 var blank = document.createElement('div');
52 blank.className = 'testHalt'; 57 blank.className = 'testHalt';
66 71
67 this.popupButton = document.createElement('button'); 72 this.popupButton = document.createElement('button');
68 this.popupButton.className = 'popupButton'; 73 this.popupButton.className = 'popupButton';
69 this.popupButton.innerHTML = 'Next'; 74 this.popupButton.innerHTML = 'Next';
70 this.popupButton.onclick = function(){popup.buttonClicked();}; 75 this.popupButton.onclick = function(){popup.buttonClicked();};
76 this.popup.style.zIndex = -1;
77 this.popup.style.visibility = 'hidden';
78 blank.style.zIndex = -2;
79 blank.style.visibility = 'hidden';
71 insertPoint.appendChild(this.popup); 80 insertPoint.appendChild(this.popup);
72 insertPoint.appendChild(blank); 81 insertPoint.appendChild(blank);
73 }; 82 };
74 83
75 this.showPopup = function(){ 84 this.showPopup = function(){
76 if (this.popup == null || this.popup == undefined) { 85 if (this.popup == null) {
77 this.createPopup(); 86 this.createPopup();
78 } 87 }
79 this.popup.style.zIndex = 3; 88 this.popup.style.zIndex = 3;
80 this.popup.style.visibility = 'visible'; 89 this.popup.style.visibility = 'visible';
81 var blank = document.getElementsByClassName('testHalt')[0]; 90 var blank = document.getElementsByClassName('testHalt')[0];
93 102
94 this.postNode = function() { 103 this.postNode = function() {
95 // This will take the node from the popupOptions and display it 104 // This will take the node from the popupOptions and display it
96 var node = this.popupOptions[this.currentIndex]; 105 var node = this.popupOptions[this.currentIndex];
97 this.popupContent.innerHTML = null; 106 this.popupContent.innerHTML = null;
98 if (node.nodeName == 'statement') { 107 if (node.type == 'statement') {
99 var span = document.createElement('span'); 108 var span = document.createElement('span');
100 span.textContent = node.textContent; 109 span.textContent = node.statement;
101 this.popupContent.appendChild(span); 110 this.popupContent.appendChild(span);
102 } else if (node.nodeName == 'question') { 111 } else if (node.type == 'question') {
103 var span = document.createElement('span'); 112 var span = document.createElement('span');
104 span.textContent = node.textContent; 113 span.textContent = node.question;
105 var textArea = document.createElement('textarea'); 114 var textArea = document.createElement('textarea');
106 var br = document.createElement('br'); 115 var br = document.createElement('br');
107 this.popupContent.appendChild(span); 116 this.popupContent.appendChild(span);
108 this.popupContent.appendChild(br); 117 this.popupContent.appendChild(br);
109 this.popupContent.appendChild(textArea); 118 this.popupContent.appendChild(textArea);
113 }; 122 };
114 123
115 this.initState = function(node) { 124 this.initState = function(node) {
116 //Call this with your preTest and postTest nodes when needed to 125 //Call this with your preTest and postTest nodes when needed to
117 // initialise the popup procedure. 126 // initialise the popup procedure.
118 this.popupOptions = $(node).children(); 127 this.popupOptions = node.options;
119 if (this.popupOptions.length > 0) { 128 if (this.popupOptions.length > 0) {
120 if (node.nodeName == 'preTest' || node.nodeName == 'PreTest') { 129 if (node.type == 'pretest') {
121 this.responses = document.createElement('PreTest'); 130 this.responses = document.createElement('PreTest');
122 } else if (node.nodeName == 'postTest' || node.nodeName == 'PostTest') { 131 } else if (node.type == 'posttest') {
123 this.responses = document.createElement('PostTest'); 132 this.responses = document.createElement('PostTest');
124 } else { 133 } else {
125 console.log ('WARNING - popup node neither pre or post!'); 134 console.log ('WARNING - popup node neither pre or post!');
126 this.responses = document.createElement('responses'); 135 this.responses = document.createElement('responses');
127 } 136 }
128 this.currentIndex = 0; 137 this.currentIndex = 0;
129 this.showPopup(); 138 this.showPopup();
130 this.postNode(); 139 this.postNode();
140 } else {
141 advanceState();
131 } 142 }
132 }; 143 };
133 144
134 this.buttonClicked = function() { 145 this.buttonClicked = function() {
135 // Each time the popup button is clicked! 146 // Each time the popup button is clicked!
136 var node = this.popupOptions[this.currentIndex]; 147 var node = this.popupOptions[this.currentIndex];
137 if (node.nodeName == 'question') { 148 if (node.type == 'question') {
138 // Must extract the question data 149 // Must extract the question data
139 var mandatory = node.attributes['mandatory'];
140 if (mandatory == undefined) {
141 mandatory = false;
142 } else {
143 if (mandatory.value == 'true'){mandatory = true;}
144 else {mandatory = false;}
145 }
146 var textArea = $(popup.popupContent).find('textarea')[0]; 150 var textArea = $(popup.popupContent).find('textarea')[0];
147 if (mandatory == true && textArea.value.length == 0) { 151 if (node.mandatory == true && textArea.value.length == 0) {
148 alert('This question is mandatory'); 152 alert('This question is mandatory');
149 return; 153 return;
150 } else { 154 } else {
151 // Save the text content 155 // Save the text content
152 var hold = document.createElement('comment'); 156 var hold = document.createElement('comment');
153 hold.id = node.attributes['id'].value; 157 hold.id = node.id;
154 hold.innerHTML = textArea.value; 158 hold.innerHTML = textArea.value;
155 console.log("Question: "+ node.textContent); 159 console.log("Question: "+ node.textContent);
156 console.log("Question Response: "+ textArea.value); 160 console.log("Question Response: "+ textArea.value);
157 this.responses.appendChild(hold); 161 this.responses.appendChild(hold);
158 } 162 }
195 console.log('NOTE - State already initialise'); 199 console.log('NOTE - State already initialise');
196 } 200 }
197 this.stateIndex = -1; 201 this.stateIndex = -1;
198 var that = this; 202 var that = this;
199 for (var id=0; id<this.stateMap.length; id++){ 203 for (var id=0; id<this.stateMap.length; id++){
200 var name = this.stateMap[id].nodeName; 204 var name = this.stateMap[id].type;
201 var obj = document.createElement(name); 205 var obj = document.createElement(name);
202 if (name == "audioHolder") {
203 obj.id = this.stateMap[id].id;
204 }
205 this.stateResults.push(obj); 206 this.stateResults.push(obj);
206 } 207 }
207 } else { 208 } else {
208 conolse.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP'); 209 conolse.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP');
209 } 210 }
214 } 215 }
215 if (this.stateIndex == -1) { 216 if (this.stateIndex == -1) {
216 console.log('Starting test...'); 217 console.log('Starting test...');
217 } 218 }
218 if (this.currentIndex == null){ 219 if (this.currentIndex == null){
219 if (this.currentStateMap.nodeName == "audioHolder") { 220 if (this.currentStateMap.type == "audioHolder") {
220 // Save current page 221 // Save current page
221 this.testPageCompleted(this.stateResults[this.stateIndex],this.currentStateMap,this.currentTestId); 222 this.testPageCompleted(this.stateResults[this.stateIndex],this.currentStateMap,this.currentTestId);
222 this.currentTestId++; 223 this.currentTestId++;
223 } 224 }
224 this.stateIndex++; 225 this.stateIndex++;
225 if (this.stateIndex >= this.stateMap.length) { 226 if (this.stateIndex >= this.stateMap.length) {
226 console.log('Test Completed'); 227 console.log('Test Completed');
227 createProjectSave(projectReturn); 228 createProjectSave(projectReturn);
228 } else { 229 } else {
229 this.currentStateMap = this.stateMap[this.stateIndex]; 230 this.currentStateMap = this.stateMap[this.stateIndex];
230 if (this.currentStateMap.nodeName == "audioHolder") { 231 if (this.currentStateMap.type == "audioHolder") {
231 console.log('Loading test page'); 232 console.log('Loading test page');
232 loadTest(this.currentStateMap); 233 loadTest(this.currentStateMap);
233 this.initialiseInnerState(this.currentStateMap); 234 this.initialiseInnerState(this.currentStateMap);
234 } else if (this.currentStateMap.nodeName == "PreTest" || this.currentStateMap.nodeName == "PostTest") { 235 } else if (this.currentStateMap.type == "pretest" || this.currentStateMap.type == "posttest") {
235 if (this.currentStateMap.childElementCount >= 1) { 236 if (this.currentStateMap.options.length >= 1) {
236 popup.initState(this.currentStateMap); 237 popup.initState(this.currentStateMap);
237 } else { 238 } else {
238 this.advanceState(); 239 this.advanceState();
239 } 240 }
240 } else { 241 } else {
248 249
249 this.testPageCompleted = function(store, testXML, testId) { 250 this.testPageCompleted = function(store, testXML, testId) {
250 // Function called each time a test page has been completed 251 // Function called each time a test page has been completed
251 // Can be used to over-rule default behaviour 252 // Can be used to over-rule default behaviour
252 253
253 pageXMLSave(store, testXML, testId); 254 pageXMLSave(store, testXML);
254 }; 255 };
255 256
256 this.initialiseInnerState = function(testXML) { 257 this.initialiseInnerState = function(node) {
257 // Parses the received testXML for pre and post test options 258 // Parses the received testXML for pre and post test options
258 this.currentStateMap = []; 259 this.currentStateMap = [];
259 var preTest = $(testXML).find('PreTest')[0]; 260 var preTest = node.preTest;
260 var postTest = $(testXML).find('PostTest')[0]; 261 var postTest = node.postTest;
261 if (preTest == undefined) {preTest = document.createElement("preTest");} 262 if (preTest == undefined) {preTest = document.createElement("preTest");}
262 if (postTest == undefined){postTest= document.createElement("postTest");} 263 if (postTest == undefined){postTest= document.createElement("postTest");}
263 this.currentStateMap.push(preTest); 264 this.currentStateMap.push(preTest);
264 this.currentStateMap.push(testXML); 265 this.currentStateMap.push(node);
265 this.currentStateMap.push(postTest); 266 this.currentStateMap.push(postTest);
266 this.currentIndex = -1; 267 this.currentIndex = -1;
267 this.advanceInnerState(); 268 this.advanceInnerState();
268 }; 269 };
269 270
272 if (this.currentIndex >= this.currentStateMap.length) { 273 if (this.currentIndex >= this.currentStateMap.length) {
273 this.currentIndex = null; 274 this.currentIndex = null;
274 this.currentStateMap = this.stateMap[this.stateIndex]; 275 this.currentStateMap = this.stateMap[this.stateIndex];
275 this.advanceState(); 276 this.advanceState();
276 } else { 277 } else {
277 if (this.currentStateMap[this.currentIndex].nodeName == "audioHolder") { 278 if (this.currentStateMap[this.currentIndex].type == "audioHolder") {
278 console.log("Loading test page"+this.currentTestId); 279 console.log("Loading test page"+this.currentTestId);
279 } else if (this.currentStateMap[this.currentIndex].nodeName == "PreTest") { 280 } else if (this.currentStateMap[this.currentIndex].type == "pretest") {
280 popup.initState(this.currentStateMap[this.currentIndex]); 281 popup.initState(this.currentStateMap[this.currentIndex]);
281 } else if (this.currentStateMap[this.currentIndex].nodeName == "PostTest") { 282 } else if (this.currentStateMap[this.currentIndex].type == "posttest") {
282 popup.initState(this.currentStateMap[this.currentIndex]); 283 popup.initState(this.currentStateMap[this.currentIndex]);
283 } else { 284 } else {
284 this.advanceInnerState(); 285 this.advanceInnerState();
285 } 286 }
286 } 287 }
325 //projectXML = $(decode); 326 //projectXML = $(decode);
326 327
327 var parse = new DOMParser(); 328 var parse = new DOMParser();
328 projectXML = parse.parseFromString(response,'text/xml'); 329 projectXML = parse.parseFromString(response,'text/xml');
329 330
330 // Now extract the setup tag 331 // Build the specification
331 var xmlSetup = projectXML.find('setup'); 332 specification.decode();
332 333
333 334 testState.stateMap.push(specification.preTest);
334 // Create pre and post test questions
335
336 var preTest = xmlSetup.find('PreTest');
337 var postTest = xmlSetup.find('PostTest');
338 preTest = preTest[0];
339 postTest = postTest[0];
340
341 if (preTest == undefined) {preTest = document.createElement("preTest");}
342 if (postTest == undefined){postTest= document.createElement("postTest");}
343
344 testState.stateMap.push(preTest);
345
346 // Extract the different test XML DOM trees
347 var audioHolders = projectXML.find('audioHolder');
348 var testXMLSetups = [];
349 audioHolders.each(function(index,element) {
350 var repeatN = element.attributes['repeatCount'].value;
351 for (var r=0; r<=repeatN; r++) {
352 testXMLSetups.push(element);
353 }
354 });
355 335
356 // New check if we need to randomise the test order 336 // New check if we need to randomise the test order
357 var randomise = xmlSetup[0].attributes['randomiseOrder']; 337 if (specification.randomiseOrder)
358 if (randomise != undefined) { 338 {
359 if (randomise.value === 'true'){ 339 specification.audioHolders = randomiseOrder(specification.audioHolders);
360 randomise = true;
361 } else {
362 randomise = false;
363 }
364 } else {
365 randomise = false;
366 } 340 }
367 341
368 if (randomise) 342 $(specification.audioHolders).each(function(index,elem){
369 {
370 testXMLSetups = randomiseOrder(testXMLSetups);
371 }
372
373 $(testXMLSetups).each(function(index,elem){
374 testState.stateMap.push(elem); 343 testState.stateMap.push(elem);
375 }); 344 });
376 345
377 testState.stateMap.push(postTest); 346 testState.stateMap.push(specification.postTest);
378 347
379 // Obtain the metrics enabled 348 // Obtain the metrics enabled
380 var metricNode = xmlSetup.find('Metric'); 349 $(specification.metrics).each(function(index,node){
381 var metricNode = metricNode.find('metricEnable');
382 metricNode.each(function(index,node){
383 var enabled = node.textContent; 350 var enabled = node.textContent;
384 switch(enabled) 351 switch(node.enabled)
385 { 352 {
386 case 'testTimer': 353 case 'testTimer':
387 sessionMetrics.prototype.enableTestTimer = true; 354 sessionMetrics.prototype.enableTestTimer = true;
388 break; 355 break;
389 case 'elementTimer': 356 case 'elementTimer':
411 }); 378 });
412 379
413 380
414 381
415 // Detect the interface to use and load the relevant javascripts. 382 // Detect the interface to use and load the relevant javascripts.
416 var interfaceType = xmlSetup[0].attributes['interface'];
417 var interfaceJS = document.createElement('script'); 383 var interfaceJS = document.createElement('script');
418 interfaceJS.setAttribute("type","text/javascript"); 384 interfaceJS.setAttribute("type","text/javascript");
419 if (interfaceType.value == 'APE') { 385 if (specification.interfaceType == 'APE') {
420 interfaceJS.setAttribute("src","ape.js"); 386 interfaceJS.setAttribute("src","ape.js");
421 387
422 // APE comes with a css file 388 // APE comes with a css file
423 var css = document.createElement('link'); 389 var css = document.createElement('link');
424 css.rel = 'stylesheet'; 390 css.rel = 'stylesheet';
448 a.hidden = ''; 414 a.hidden = '';
449 a.href = dnlk; 415 a.href = dnlk;
450 a.download = "save.xml"; 416 a.download = "save.xml";
451 a.textContent = "Save File"; 417 a.textContent = "Save File";
452 418
453 var submitDiv = document.getElementById('download-point');
454 submitDiv.appendChild(a);
455 popup.showPopup(); 419 popup.showPopup();
456 popup.popupContent.innerHTML = null; 420 popup.popupContent.innerHTML = null;
457 popup.popupContent.appendChild(submitDiv) 421 popup.popupContent.appendChild(a)
458 } else { 422 } else {
459 var xmlhttp = new XMLHttpRequest; 423 var xmlhttp = new XMLHttpRequest;
460 xmlhttp.open("POST",destURL,true); 424 xmlhttp.open("POST",destURL,true);
461 xmlhttp.setRequestHeader('Content-Type', 'text/xml'); 425 xmlhttp.setRequestHeader('Content-Type', 'text/xml');
462 xmlhttp.onerror = function(){ 426 xmlhttp.onerror = function(){
1001 if (setupNode.getAttribute('collectMetrics') == "true") { 965 if (setupNode.getAttribute('collectMetrics') == "true") {
1002 this.collectMetrics = true; 966 this.collectMetrics = true;
1003 } else {this.setup.collectMetrics = false;} 967 } else {this.setup.collectMetrics = false;}
1004 var metricCollection = setupNode.getElementsByTagName('Metric'); 968 var metricCollection = setupNode.getElementsByTagName('Metric');
1005 969
1006 this.preTest = new this.prepostNode('pre',setupNode.getElementsByTagName('PreTest')); 970 this.preTest = new this.prepostNode('pretest',setupNode.getElementsByTagName('PreTest'));
1007 this.postTest = new this.prepostNode('post',setupNode.getElementsByTagName('PostTest')); 971 this.postTest = new this.prepostNode('posttest',setupNode.getElementsByTagName('PostTest'));
1008 972
1009 if (metricCollection.length > 0) { 973 if (metricCollection.length > 0) {
1010 metricCollection = metricCollection[0].getElementsByTagName('metricEnable'); 974 metricCollection = metricCollection[0].getElementsByTagName('metricEnable');
1011 for (var i=0; i<metricCollection.length; i++) { 975 for (var i=0; i<metricCollection.length; i++) {
1012 this.metrics.push(new this.metricNode(metricCollection[0].textContent)); 976 this.metrics.push(new this.metricNode(metricCollection[i].textContent));
1013 } 977 }
1014 } 978 }
1015 979
1016 var audioHolders = projectXML.getElementsByTagName('audioHolder'); 980 var audioHolders = projectXML.getElementsByTagName('audioHolder');
1017 for (var i=0; i<audioHolders.length; i++) { 981 for (var i=0; i<audioHolders.length; i++) {
1031 this.mandatory; 995 this.mandatory;
1032 if (child.getAttribute('mandatory') == "true") {this.mandatory = true;} 996 if (child.getAttribute('mandatory') == "true") {this.mandatory = true;}
1033 else {this.mandatory = false;} 997 else {this.mandatory = false;}
1034 this.question = child.textContent; 998 this.question = child.textContent;
1035 } else if (child.nodeName == "statement") { 999 } else if (child.nodeName == "statement") {
1036 this.statment = child.textContent; 1000 this.statement = child.textContent;
1037 } 1001 }
1038 }; 1002 };
1039 1003
1040 // On construction: 1004 // On construction:
1041 if (Collection.length != 0) { 1005 if (Collection.length != 0) {
1050 this.metricNode = function(name) { 1014 this.metricNode = function(name) {
1051 this.enabled = name; 1015 this.enabled = name;
1052 }; 1016 };
1053 1017
1054 this.audioHolderNode = function(parent,xml) { 1018 this.audioHolderNode = function(parent,xml) {
1019 this.type = 'audioHolder';
1055 this.interfaceNode = function(DOM) { 1020 this.interfaceNode = function(DOM) {
1056 var title = DOM.getElementsByTagName('title'); 1021 var title = DOM.getElementsByTagName('title');
1057 if (title.length == 0) {this.title = null;} 1022 if (title.length == 0) {this.title = null;}
1058 else {this.title = title[0].textContent;} 1023 else {this.title = title[0].textContent;}
1059 1024
1088 if (xml.getAttribute('loop') == 'true') {this.loop = true;} 1053 if (xml.getAttribute('loop') == 'true') {this.loop = true;}
1089 else {this.loop == false;} 1054 else {this.loop == false;}
1090 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;} 1055 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;}
1091 else {this.elementComments = false;} 1056 else {this.elementComments = false;}
1092 1057
1093 this.preTest = new parent.prepostNode('pre',xml.getElementsByTagName('PreTest')); 1058 this.preTest = new parent.prepostNode('pretest',xml.getElementsByTagName('PreTest'));
1094 this.postTest = new parent.prepostNode('post',xml.getElementsByTagName('PostTest')); 1059 this.postTest = new parent.prepostNode('posttest',xml.getElementsByTagName('PostTest'));
1095 1060
1096 this.interfaces = []; 1061 this.interfaces = [];
1097 var interfaceDOM = xml.getElementsByTagName('interface'); 1062 var interfaceDOM = xml.getElementsByTagName('interface');
1098 for (var i=0; i<interfaceDOM.length; i++) { 1063 for (var i=0; i<interfaceDOM.length; i++) {
1099 this.interfaces.push(new this.interfaceNode(interfaceDOM[i])); 1064 this.interfaces.push(new this.interfaceNode(interfaceDOM[i]));