comparison test_create/test_create.html @ 311:f46398fdf56c Dev_main

Updating test create using questions
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Wed, 23 Sep 2015 11:42:11 +0100
parents 0518fc661e7b
children f73d9333ab0d
comparison
equal deleted inserted replaced
304:bcfce203ec91 311:f46398fdf56c
5 5
6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame 6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
7 Remove this if you use the .htaccess --> 7 Remove this if you use the .htaccess -->
8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9 9
10 <title>WAET Create Test</title> 10 <title>WAET: Test Creator</title>
11 <meta name="description" content="">
12 <meta name="author" content="">
13 11
14 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 12 <meta name="viewport" content="width=device-width; initial-scale=1.0">
13 <script type="text/javascript">
15 14
16 <script type="text/javascript"> 15 var APEInterfaceOptions = [["playhead","page-count"],["Show the playhead/scrubber bar", "Show test page count"]];
17 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file! 16 var APEInterfaceChecks = [["fragmentPlayed","fragmentFullPlayback","fragmentMoved","fragmentComments"],["All Fragments Played","All Fragments Played in entirety","All sliders moved","All fragments have comments"]];
18 var topLevel; 17 var MUSHRAInterfaceOptions = [[],[]];
19 window.onload = function() { 18 var MUSHRAInterfaceChecks = [["fragmentPlayed","fragmentMoved","fragmentComments"],["All Fragments Played","All sliders moved","All fragments have comments"]];
20 // Initialise page 19 var popupInstance;
21 topLevel = document.getElementById('topLevelBody'); 20 var specificationNode;
22 var setup = document.createElement('div'); 21 var audioContext;
23 setup.id = 'setupTagDiv'; 22 window.onload = function()
24 23 {
25 // Setup drag/drop handles 24 var AudioContext = window.AudioContext || window.webkitAudioContext;
26 var dropBody = document.getElementById('dragFile'); 25 audioContext = new AudioContext;
27 dropBody.addEventListener('dragover', handleDragOver, false); 26 popupInstance = new popup();
28 dropBody.addEventListener('dragenter',handleDragEnter,false); 27 popupInstance.advanceState();
29 dropBody.addEventListener('dragleave',handleDragLeave,false); 28 specificationNode = new Specification();
30 dropBody.addEventListener('drop', handleDrop,false);
31 }; 29 };
32 30
33 function attributePair(string, type, mandatory){ 31 function popup()
34 var id = document.createElement("span"); 32 {
35 id.textContent = string; 33 var x = window.innerWidth;
36 var input = document.createElement("input"); 34 var y = window.innerHeight;
37 input.type = type; 35 this.popupHolder = document.createElement('div');
38 if (type == 'text') { 36 this.popupHolder.style.visibility = 'hidden';
39 if (mandatory == true) { 37 this.popupContent = document.createElement('div');
40 input.setAttribute('mandatory','true'); 38 this.popupTitle = document.createElement('div');
41 } 39 this.popupBody = document.createElement('div');
42 else { 40 this.popupFooter = document.createElement('div');
43 input.setAttribute('mandatory','false'); 41 this.popupTitleText = document.createElement('span');
44 } 42 this.popupTitle.appendChild(this.popupTitleText);
45 } 43
46 return [id, input]; 44 this.popupHolder.className = "popup";
47 } 45 this.popupHolder.style.left = (x-500)/2 +'px';
46 this.popupHolder.style.top = (y-400)/2 + 'px';
47 this.popupContent.style.padding = "20px";
48 this.popupHolder.appendChild(this.popupContent);
49
50 this.popupTitle.style.width = "100%";
51 this.popupTitle.style.height = "50px";
52 this.popupTitle.style.fontSize = "xx-large";
53 this.popupContent.appendChild(this.popupTitle);
54
55 this.popupBody.style.width = "100%";
56 this.popupBody.style.height = "280px";
57 this.popupContent.appendChild(this.popupBody);
58
59 this.popupFooter.style.width = "100%";
60 this.popupFooter.style.height = "30px";
61 this.popupContent.appendChild(this.popupFooter);
62 var body = document.getElementsByTagName('body')[0];
63 body.appendChild(this.popupHolder);
64
65 this.pageBlank = document.createElement('div');
66 body.appendChild(this.pageBlank);
67 this.pageBlank.style.width = "100%";
68 this.pageBlank.style.height = "100%";
69 this.pageBlank.style.position = "absolute";
70 this.pageBlank.style.left = "0px";
71 this.pageBlank.style.top = "0px";
72 this.pageBlank.style.backgroundColor = "rgba(0,0,0,0.5)";
73 this.pageBlank.style.visibility = 'hidden';
74
75 this.state = 0;
76
77 this.showPopup = function()
78 {
79 this.popupHolder.style.visibility = 'visible';
80 this.popupHolder.style.zIndex = "3";
81 this.pageBlank.style.visibility = 'visible';
82 this.pageBlank.style.zIndex = "2";
83 };
84
85 this.hidePopup = function()
86 {
87 this.popupHolder.style.visibility = 'hidden';
88 this.popupHolder.style.zIndex = "-1";
89 this.pageBlank.style.visibility = 'hidden';
90 this.pageBlank.style.zIndex = "-2";
91 };
92
93 this.init = function()
94 {
95 this.popupTitleText.textContent = "Welcome";
96 var text = document.createElement('span');
97 text.textContent = "Thank you for downloading the Web Audio Evaluation Toolbox. This page will help guide you through creating the documents required to run a test. If you have an existing XML file you wish to edit, please drag and drop it into the box below";
98 var dnd = document.createElement('div');
99 dnd.style.width = "100%";
100 dnd.style.height = "50px";
101 dnd.className = "dragndrop";
102 this.popupBody.appendChild(text);
103 this.popupBody.appendChild(dnd);
104 this.showPopup();
105
106 var button = document.createElement('button');
107 button.className = "popupButton";
108 button.textContent = "New File";
109 button.onclick = function(event) {
110 popupInstance.advanceState();
111 };
112 this.popupFooter.appendChild(button);
113 };
114
115 this.advanceState = function()
116 {
117 this.popupBody.innerHTML = null;
118 this.popupFooter.innerHTML = null;
119 this.popupTitleText.textContent = null;
120 switch(this.state)
121 {
122 case 0:
123 this.init();
124 break;
125 case 1:
126 this.popupTitleText.textContent = "Test Type";
127 var text = document.createElement("span");
128 text.textContent = "What type of test would you like to use. Currently APE (Audio Perceptual Evaluation) and MUSHRA style interfaces are available";
129 this.popupBody.appendChild(text);
130 var select = document.createElement("select");
131 select.id="interface-select";
132 var opt1 = document.createElement("option");
133 opt1.value = "APE";
134 opt1.textContent = "APE";
135 select.appendChild(opt1);
136 var opt2 = document.createElement("option");
137 opt2.value = "MUSHRA";
138 opt2.textContent = "MUSHRA";
139 select.appendChild(opt2);
140 this.popupBody.appendChild(select);
141
142 var button = document.createElement('button');
143 button.className = "popupButton";
144 button.textContent = "Submit";
145 button.onclick = function(event) {
146 var select = document.getElementById("interface-select");
147 specificationNode.interfaceType = select.value;
148 specificationNode.collectMetrics = true;
149 popupInstance.advanceState();
150 };
151 this.popupFooter.appendChild(button);
152 break;
153 case 2:
154 this.popupTitleText.textContent = "Test Options";
155 var holder = document.createElement('div');
156 holder.style.margin = "5px";
157 var checkbox = document.createElement('input');
158 checkbox.type = 'checkbox';
159 checkbox.id = "Randomise-Page";
160 var text = document.createElement('span');
161 text.textContent = "Randomise Page Order";
162 holder.appendChild(checkbox);
163 holder.appendChild(text);
164 this.popupBody.appendChild(holder);
165 switch(specificationNode.interfaceType)
166 {
167 case "APE":
168 for (var i=0; i<APEInterfaceOptions[0].length; i++)
169 {
170 holder = document.createElement('div');
171 holder.style.margin = "5px";
172 checkbox = document.createElement('input');
173 checkbox.type = 'checkbox';
174 checkbox.setAttribute("name","option");
175 checkbox.id = APEInterfaceOptions[0][i];
176 text = document.createElement('span');
177 text.textContent = APEInterfaceOptions[1][i];
178 holder.appendChild(checkbox);
179 holder.appendChild(text);
180 this.popupBody.appendChild(holder);
181 }
182 for (var i=0; i<APEInterfaceChecks[0].length; i++)
183 {
184 holder = document.createElement('div');
185 holder.style.margin = "5px";
186 checkbox = document.createElement('input');
187 checkbox.type = 'checkbox';
188 checkbox.setAttribute("name","check");
189 checkbox.id = APEInterfaceChecks[0][i];
190 text = document.createElement('span');
191 text.textContent = APEInterfaceChecks[1][i];
192 holder.appendChild(checkbox);
193 holder.appendChild(text);
194 this.popupBody.appendChild(holder);
195 }
196 break;
197 case "MUSHRA":
198 for (var i=0; i<MUSHRAInterfaceOptions[0].length; i++)
199 {
200 holder = document.createElement('div');
201 holder.style.margin = "5px";
202 checkbox = document.createElement('input');
203 checkbox.type = 'checkbox';
204 checkbox.setAttribute("name","option");
205 checkbox.id = MUSHRAInterfaceOptions[0][i];
206 text = document.createElement('span');
207 text.textContent = MUSHRAInterfaceOptions[1][i];
208 holder.appendChild(checkbox);
209 holder.appendChild(text);
210 this.popupBody.appendChild(holder);
211 }
212 for (var i=0; i<MUSHRAInterfaceChecks[0].length; i++)
213 {
214 holder = document.createElement('div');
215 holder.style.margin = "5px";
216 checkbox = document.createElement('input');
217 checkbox.type = 'checkbox';
218 checkbox.setAttribute("name","check");
219 checkbox.id = MUSHRAInterfaceChecks[0][i];
220 text = document.createElement('span');
221 text.textContent = MUSHRAInterfaceChecks[1][i];
222 holder.appendChild(checkbox);
223 holder.appendChild(text);
224 this.popupBody.appendChild(holder);
225 }
226 }
227 var button = document.createElement('button');
228 button.className = "popupButton";
229 button.textContent = "Submit";
230 button.onclick = function(event) {
231 var optHold = popupInstance.popupBody;
232 var opt = optHold.firstChild;
233 var input = opt.getElementsByTagName('input')[0];
234 specificationNode.randomiseOrder = input.checked;
235 while(opt.nextSibling != null)
236 {
237 opt = opt.nextSibling;
238 input = opt.getElementsByTagName('input')[0];
239 if (input.checked)
240 {
241 specificationNode.commonInterface.options.push(new specificationNode.commonInterface.optionNode(input));
242 }
243
244 }
245 popupInstance.advanceState();
246 };
247 this.popupFooter.appendChild(button);
248 break;
249 case 3:
250 this.popupTitleText.textContent = "Test Page";
251 var span = document.createElement('span');
252 span.textContent = "Drag and drop your audio files into the box below to add them to a test page";
253 this.popupBody.appendChild(span);
254 var dnd = document.createElement('div');
255 dnd.id = "audio-holder-drop";
256 dnd.style.width = "100%";
257 dnd.style.minHeight = "50px";
258 dnd.style.maxHeight = "220px";
259 dnd.style.overflow = 'auto';
260 dnd.className = "dragndrop";
261 dnd.ondragover = function(e) {
262 if(e.preventDefault) {e.preventDefault();}
263 return false;
264 };
265 dnd.ondragenter = function(e) {
266 if(e.preventDefault) {e.preventDefault();}
267 return false;
268 };
269 dnd.ondrop = function(e) {
270 if(e.preventDefault) {e.preventDefault();}
271 var dt = e.dataTransfer;
272 var body = document.getElementById("audio-holder-drop");
273 var files = dt.files;
274 for (var i = 0, f; f = files[i]; i++)
275 {
276 var dndHeader = document.createElement('div');
277 dndHeader.style.width = "100%";
278 dndHeader.style.height = "20px";
279 dndHeader.style.borderBottom = "#DDD";
280 dndHeader.style.borderBottomWidth = "1px";
281 dndHeader.style.borderBottomStyle = "solid";
282 var dndHInclude = document.createElement('div');
283 dndHInclude.style.width = "30px";
284 dndHInclude.className = "dndheaderelement";
285 var includeCheck = document.createElement('input');
286 includeCheck.type = "checkbox";
287 includeCheck.name = "include-check";
288 includeCheck.checked = true;
289 dndHInclude.appendChild(includeCheck);
290 dndHeader.appendChild(dndHInclude);
291 var dndHTitle = document.createElement('div');
292 dndHTitle.style.width = "180px";
293 dndHTitle.className = "dndheaderelement";
294 var text = document.createElement('span');
295 text.textContent = f.name;
296 dndHTitle.appendChild(text);
297 dndHeader.appendChild(dndHTitle);
298 var dndHID = document.createElement('div');
299 dndHID.style.width = "100px";
300 dndHID.className = "dndheaderelement";
301 var IDInput = document.createElement('input');
302 IDInput.name = "ID";
303 IDInput.value = f.name.split('.')[0];
304 IDInput.style.width = "96px";
305 // TODO: Automatic checking for common ID;
306 dndHID.appendChild(IDInput);
307 dndHeader.appendChild(dndHID);
308 var dndHPlay = document.createElement('div');
309 dndHPlay.style.width = "100px";
310 dndHPlay.className = "dndheaderelement";
311 var audio = document.createElement('audio');
312 dndHPlay.appendChild(audio);
313 dndHeader.appendChild(dndHPlay);
314 dnd.appendChild(dndHeader);
315 }
316 };
317 var dndHeader = document.createElement('div');
318 dndHeader.style.width = "100%";
319 dndHeader.style.height = "15px";
320 dndHeader.style.borderBottom = "#DDD";
321 dndHeader.style.borderBottomWidth = "1px";
322 dndHeader.style.borderBottomStyle = "solid";
323 var dndHInclude = document.createElement('div');
324 dndHInclude.style.width = "30px";
325 dndHInclude.className = "dndheaderelement";
326 var text = document.createElement('span');
327 text.textContent = "Inc.";
328 dndHInclude.appendChild(text);
329 dndHeader.appendChild(dndHInclude);
330 var dndHTitle = document.createElement('div');
331 dndHTitle.style.width = "180px";
332 dndHTitle.className = "dndheaderelement";
333 text = document.createElement('span');
334 text.textContent = "File Name";
335 dndHTitle.appendChild(text);
336 dndHeader.appendChild(dndHTitle);
337 var dndHID = document.createElement('div');
338 dndHID.style.width = "100px";
339 dndHID.className = "dndheaderelement";
340 text = document.createElement('span');
341 text.textContent = "ID";
342 dndHID.appendChild(text);
343 dndHeader.appendChild(dndHID);
344 var dndHPlay = document.createElement('div');
345 dndHPlay.style.width = "100px";
346 dndHPlay.className = "dndheaderelement";
347 text = document.createElement('span');
348 text.textContent = "Sample";
349 dndHPlay.appendChild(text);
350 dndHeader.appendChild(dndHPlay);
351 dnd.appendChild(dndHeader);
352 this.popupBody.appendChild(dnd);
353 var button = document.createElement('button');
354 button.className = "popupButton";
355 button.textContent = "Submit";
356 button.onclick = function(event)
357 {
358
359 };
360 this.popupFooter.appendChild(button);
361 }
362 this.state++;
363 };
364 };
48 365
49 function removeNode(event) { 366 function Specification() {
50 event.srcElement.parentElement.parentElement.removeChild(event.srcElement.parentElement); 367 // Handles the decoding of the project specification XML into a simple JavaScript Object.
51 } 368
52 369 this.interfaceType = null;
53 function buttonClickedValidate() { 370 this.commonInterface = new function()
54 var ready = validate(); 371 {
55 if (ready == false) { 372 this.options = [];
56 var errMsg = document.getElementById('errorMessage'); 373 this.optionNode = function(input)
57 errMsg.textContent = "There were some errors with your XML. Any input boxes highlighted in red are invalid because they are empty or because its ID matches another elements ID. Please fill these in correctly. Any boxes which are yellow are not-invalid but will use the default value."; 374 {
58 errMsg.style.visibility = 'visible'; 375 var name = input.getAttribute('name');
59 document.getElementById('createXML').disabled = true; 376 this.type = name;
60 377 if(this.type == "option")
61 } else { 378 {
62 var errMsg = document.getElementById('errorMessage'); 379 this.name = input.id;
63 errMsg.textContent = ""; 380 } else if (this.type == "check")
64 errMsg.style.visiblity = 'hidden'; 381 {
65 document.getElementById('createXML').disabled = false; 382 this.check = input.id;
66 } 383 }
67 } 384 };
68 385 };
69 function buttonClickedSubmit() { 386 this.projectReturn = null;
70 var ready = validate(); 387 this.randomiseOrder = null;
71 if (ready == true) { 388 this.collectMetrics = null;
72 var xmlDoc = buildXML(); 389 this.testPages = null;
73 var inject = document.getElementById('errorMessage'); 390 this.preTest = null;
74 createProjectSave(xmlDoc, inject); 391 this.postTest = null;
75 } 392 this.audioHolders = [];
76 } 393
77 394 this.decode = function() {
78 function createProjectSave(xmlDoc, injectPoint) { 395 // projectXML - DOM Parsed document
79 var parent = document.createElement("div"); 396 this.projectXML = projectXML.childNodes[0];
80 parent.appendChild(xmlDoc); 397 var setupNode = projectXML.getElementsByTagName('setup')[0];
81 var file = [parent.innerHTML]; 398 this.interfaceType = setupNode.getAttribute('interface');
82 var bb = new Blob(file,{type : 'application/xml'}); 399 this.projectReturn = setupNode.getAttribute('projectReturn');
83 var dnlk = window.URL.createObjectURL(bb); 400 this.testPages = setupNode.getAttribute('testPages');
84 var a = document.createElement("a"); 401 if (setupNode.getAttribute('randomiseOrder') == "true") {
85 a.hidden = ''; 402 this.randomiseOrder = true;
86 a.href = dnlk; 403 } else {this.randomiseOrder = false;}
87 a.download = "save.xml"; 404 if (setupNode.getAttribute('collectMetrics') == "true") {
88 a.textContent = "Save File"; 405 this.collectMetrics = true;
89 injectPoint.appendChild(a); 406 } else {this.collectMetrics = false;}
90 } 407 if (isNaN(Number(this.testPages)) || this.testPages == undefined)
91 408 {
92 function buildXML() { 409 this.testPages = null;
93 var xmlDoc = document.createElement('BrowserEvalProjectDocument'); 410 } else {
94 var setup = document.createElement('setup'); 411 this.testPages = Number(this.testPages);
95 setup.setAttribute('interface',document.getElementById('interface').value); 412 if (this.testPages == 0) {this.testPages = null;}
96 if (document.getElementById('projectReturn').value == "") { 413 }
97 setup.setAttribute('projectReturn',"null"); 414 var metricCollection = setupNode.getElementsByTagName('Metric');
98 } else { 415
99 setup.setAttribute('projectReturn',document.getElementById('projectReturn').value); 416 this.preTest = new this.prepostNode('pretest',setupNode.getElementsByTagName('PreTest'));
100 } 417 this.postTest = new this.prepostNode('posttest',setupNode.getElementsByTagName('PostTest'));
101 setup.setAttribute('randomiseOrder',document.getElementById('randomisePageOrder').checked); 418
102 setup.setAttribute('collectMetrics',document.getElementById('collectMetrics').checked); 419 if (metricCollection.length > 0) {
103 420 metricCollection = metricCollection[0].getElementsByTagName('metricEnable');
104 var globalPreTest = document.createElement('preTest'); 421 for (var i=0; i<metricCollection.length; i++) {
105 var options = document.getElementById('globalPreTest').getElementsByClassName('head'); 422 this.metrics.push(new this.metricNode(metricCollection[i].textContent));
106 constructPrePost(globalPreTest, options); 423 }
107 424 }
108 var globalPostTest = document.createElement('postTest'); 425
109 options = document.getElementById('globalPostTest').getElementsByClassName('head'); 426 var commonInterfaceNode = setupNode.getElementsByTagName('interface');
110 constructPrePost(globalPostTest, options); 427 if (commonInterfaceNode.length > 0) {
111 428 commonInterfaceNode = commonInterfaceNode[0];
112 var globalMetrics = document.createElement('metric'); 429 } else {
113 options = document.getElementById('globalMetric').getElementsByClassName('attrib')[0].getElementsByTagName('input'); 430 commonInterfaceNode = undefined;
114 for (var i=0; i<options.length; i++) { 431 }
115 if (options[i].checked) { 432
116 var metric = document.createElement('metricEnable'); 433 this.commonInterface = new function() {
117 metric.textContent = options[i].id; 434 this.OptionNode = function(child) {
118 globalMetrics.appendChild(metric); 435 this.type = child.nodeName;
119 } 436 if (this.type == 'option')
120 } 437 {
121 setup.appendChild(globalPreTest); 438 this.name = child.getAttribute('name');
122 setup.appendChild(globalPostTest); 439 }
123 setup.appendChild(globalMetrics); 440 else if (this.type == 'check') {
124 xmlDoc.appendChild(setup); 441 this.check = child.getAttribute('name');
125 442 if (this.check == 'scalerange') {
126 var audioHolders = document.getElementsByName('audio-holder'); 443 this.min = child.getAttribute('min');
127 for (var i=0; i<audioHolders.length; i++) { 444 this.max = child.getAttribute('max');
128 var audioHolder = document.createElement('audioHolder'); 445 if (this.min == null) {this.min = 1;}
129 var audioHolderDOM = audioHolders[i]; 446 else if (Number(this.min) > 1 && this.min != null) {
130 var attribs = audioHolderDOM.getElementsByClassName('attrib')[0].getElementsByTagName('input'); 447 this.min = Number(this.min)/100;
131 audioHolder.id = attribs[0].value; 448 } else {
132 if (attribs[1].value != "") {audioHolder.setAttribute('sampleRate',attribs[1].value);} 449 this.min = Number(this.min);
133 if (attribs[2].value != "") {audioHolder.setAttribute('hostURL',attribs[2].value);} 450 }
134 audioHolder.setAttribute('randomiseOrder',attribs[3].checked); 451 if (this.max == null) {this.max = 0;}
135 audioHolder.setAttribute('repeatCount',attribs[4].checked); 452 else if (Number(this.max) > 1 && this.max != null) {
136 audioHolder.setAttribute('loop',attribs[5].checked); 453 this.max = Number(this.max)/100;
137 audioHolder.setAttribute('elementComments',attribs[6].checked); 454 } else {
138 455 this.max = Number(this.max);
139 // Audio-Holder PreTests
140 var audioHolderPreTest = document.createElement('preTest');
141 var audioHolderPostTest = document.createElement('postTest');
142 options = audioHolderDOM.childNodes[2].getElementsByClassName('head');
143 constructPrePost(audioHolderPreTest, options);
144 options = audioHolderDOM.childNodes[3].getElementsByClassName('head');
145 constructPrePost(audioHolderPostTest, options);
146
147 audioHolder.appendChild(audioHolderPreTest);
148 audioHolder.appendChild(audioHolderPostTest);
149
150 // Interface Nodes
151
152 // audio-Elements
153 var audioElementsDOM = [];
154 var commentQuestionDOM = [];
155 var interfacesDOM = [];
156 for (var j=0; j<audioHolderDOM.childElementCount; j++) {
157 var child = audioHolderDOM.childNodes[j];
158 var name = child.getAttribute('name');
159 if (name == 'audio-element') {audioElementsDOM.push(child);}
160 else if (name == 'comment-question') {commentQuestionDOM.push(child);}
161 else if (name == 'interface-options') {interfacesDOM.push(child);}
162 }
163
164 for (var j=0; j<interfacesDOM.length; j++) {
165 var interfaceNode = document.createElement('interface');
166 attribs = interfacesDOM[j].getElementsByClassName('attrib')[0].getElementsByTagName('input');
167 var title = document.createElement('title');
168 title.textContent = attribs[0].value;
169 interfaceNode.appendChild(title);
170
171
172 var markers = interfacesDOM[j].getElementsByClassName('head');
173 for (var k=0; k<markers.length; k++) {
174 var markerNode = document.createElement('scale');
175 attribs = markers[k].getElementsByClassName('attrib')[0].getElementsByTagName('input');
176 markerNode.textContent = attribs[0].value;
177 markerNode.setAttribute('position',attribs[1].value);
178 interfaceNode.appendChild(markerNode);
179 }
180 audioHolder.appendChild(interfaceNode);
181 }
182
183 for (var j=0; j<audioElementsDOM.length; j++) {
184 var audioElement = document.createElement('audioElement');
185 attribs = audioElementsDOM[j].getElementsByClassName('attrib')[0].getElementsByTagName('input');
186 audioElement.id = attribs[0].value;
187 audioElement.setAttribute('url',attribs[1].value);
188 audioHolder.appendChild(audioElement);
189 }
190
191 for (var j=0; j<commentQuestionDOM.length; j++) {
192 var commentQuestion = document.createElement('commentQuestion');
193 attribs = commentQuestionDOM[j].getElementsByClassName('attrib')[0].getElementsByTagName('input');
194 commentQuestion.id = attribs[0].value;
195 commentQuestion.textContent = attribs[1].value;
196 audioHolder.appendChild(commentQuestion);
197 }
198 xmlDoc.appendChild(audioHolder);
199 }
200 return xmlDoc;
201 }
202
203 function constructPrePost(parent, options) {
204 for (var i=0; i<options.length; i++) {
205 var elem = options[i];
206 var attributes = elem.getElementsByClassName('attrib')[0].getElementsByTagName('input');
207 if (elem.getAttribute('name') == 'question-node') {
208 var node = document.createElement('question');
209 node.setAttribute('id',attributes[0].value);
210 node.textContent = attributes[1].value;
211 node.setAttribute('mandatory',attributes[2].checked);
212 } else if (elem.getAttribute('name') == 'statement-node') {
213 var node = document.createElement('statement');
214 node.textContent = attributes[0].value;
215 }
216 parent.appendChild(node);
217 }
218 }
219
220 function validate() {
221 var canExport = true;
222 // Checks if the XML can be created from the given entries
223 var inputs = document.getElementsByTagName('input');
224 for (var i=0; i<inputs.length; i++) {
225 if (inputs[i].type == 'text') {
226 if (inputs[i].value == "") {
227 var mandatory = inputs[i].getAttribute('mandatory');
228 if (mandatory == "true") {
229 errorInput(inputs[i]);
230 canExport = false;
231 } else {
232 warningInput(inputs[i]);
233 }
234 } else {
235 goodInput(inputs[i]);
236 }
237 }
238 }
239
240 var audioHolders = document.getElementsByName('audio-holder');
241 for (var i=0; i<audioHolders.length; i++) {
242 var divs = audioHolders[i].getElementsByClassName('head');
243 var IDs = [];
244 for (var j=0; j<divs.length; j++) {
245 if (divs[j].getAttribute('name') == 'audio-element') {
246 var obj = divs[j].getElementsByClassName('attrib')[0].children[1];
247 var aeID = obj.value;
248 if (aeID != "") {
249 var unique = true;
250 for (var k=0; k<IDs.length; k++) {
251 if (aeID == IDs[k]) {
252 unique = false;
253 break;
254 } 456 }
255 } 457 }
256 if (unique == true) { 458 } else if (this.type == 'anchor' || this.type == 'reference') {
257 IDs.push(aeID); 459 this.value = Number(child.textContent);
258 } else { 460 this.enforce = child.getAttribute('enforce');
259 errorInput(obj); 461 if (this.enforce == 'true') {this.enforce = true;}
260 canExport = false; 462 else {this.enforce = false;}
463 }
464 };
465 this.options = [];
466 if (commonInterfaceNode != undefined) {
467 var child = commonInterfaceNode.firstElementChild;
468 while (child != undefined) {
469 this.options.push(new this.OptionNode(child));
470 child = child.nextElementSibling;
471 }
472 }
473 };
474
475 var audioHolders = projectXML.getElementsByTagName('audioHolder');
476 for (var i=0; i<audioHolders.length; i++) {
477 this.audioHolders.push(new this.audioHolderNode(this,audioHolders[i]));
478 }
479
480 // New check if we need to randomise the test order
481 if (this.randomiseOrder)
482 {
483 this.audioHolders = randomiseOrder(this.audioHolders);
484 for (var i=0; i<this.audioHolders.length; i++)
485 {
486 this.audioHolders[i].presentedId = i;
487 }
488 }
489
490 if (this.testPages != null || this.testPages != undefined)
491 {
492 if (this.testPages > audioHolders.length)
493 {
494 console.log('Warning: You have specified '+audioHolders.length+' tests but requested '+this.testPages+' be completed!');
495 this.testPages = audioHolders.length;
496 }
497 var aH = this.audioHolders;
498 this.audioHolders = [];
499 for (var i=0; i<this.testPages; i++)
500 {
501 this.audioHolders.push(aH[i]);
502 }
503 }
504 };
505
506 this.prepostNode = function(type,Collection) {
507 this.type = type;
508 this.options = [];
509
510 this.OptionNode = function(child) {
511
512 this.childOption = function(element) {
513 this.type = 'option';
514 this.id = element.id;
515 this.name = element.getAttribute('name');
516 this.text = element.textContent;
517 };
518
519 this.type = child.nodeName;
520 if (child.nodeName == "question") {
521 this.id = child.id;
522 this.mandatory;
523 if (child.getAttribute('mandatory') == "true") {this.mandatory = true;}
524 else {this.mandatory = false;}
525 this.question = child.textContent;
526 if (child.getAttribute('boxsize') == null) {
527 this.boxsize = 'normal';
528 } else {
529 this.boxsize = child.getAttribute('boxsize');
530 }
531 } else if (child.nodeName == "statement") {
532 this.statement = child.textContent;
533 } else if (child.nodeName == "checkbox" || child.nodeName == "radio") {
534 var element = child.firstElementChild;
535 this.id = child.id;
536 if (element == null) {
537 console.log('Malformed' +child.nodeName+ 'entry');
538 this.statement = 'Malformed' +child.nodeName+ 'entry';
539 this.type = 'statement';
540 } else {
541 this.options = [];
542 while (element != null) {
543 if (element.nodeName == 'statement' && this.statement == undefined){
544 this.statement = element.textContent;
545 } else if (element.nodeName == 'option') {
546 this.options.push(new this.childOption(element));
547 }
548 element = element.nextElementSibling;
261 } 549 }
262 } 550 }
263 } 551 } else if (child.nodeName == "number") {
264 } 552 this.statement = child.textContent;
265 } 553 this.id = child.id;
266 return canExport; 554 this.min = child.getAttribute('min');
267 }; 555 this.max = child.getAttribute('max');
268 556 this.step = child.getAttribute('step');
269 function errorInput(node) { 557 }
270 node.style.backgroundColor = "#FF0000"; 558 };
271 } 559
272 560 // On construction:
273 function warningInput(node) { 561 if (Collection.length != 0) {
274 node.style.backgroundColor = "#FFFF00"; 562 Collection = Collection[0];
275 } 563 if (Collection.childElementCount != 0) {
276 564 var child = Collection.firstElementChild;
277 function goodInput(node) { 565 this.options.push(new this.OptionNode(child));
278 node.style.backgroundColor = "#FFFFFF"; 566 while (child.nextElementSibling != null) {
279 } 567 child = child.nextElementSibling;
280 568 this.options.push(new this.OptionNode(child));
281 function questionNode() { 569 }
282 var node = document.createElement("div"); 570 }
283 node.setAttribute('class','head'); 571 }
284 node.setAttribute('name','question-node');
285 var nodeTitle = document.createElement("span");
286 nodeTitle.textContent = "Question";
287 var attributes = document.createElement("div");
288 attributes.setAttribute('class','attrib');
289 var id = attributePair("ID:","text", true);
290 var question = attributePair("Question:","text", false);
291 question[1].style.width = "500px";
292 var mandatory = attributePair("Mandatory:","checkbox", false);
293 node.appendChild(nodeTitle);
294 id.forEach(function(item){attributes.appendChild(item);},false);
295 question.forEach(function(item){attributes.appendChild(item);},false);
296 mandatory.forEach(function(item){attributes.appendChild(item);},false);
297 node.appendChild(attributes);
298
299 var removeButton = document.createElement("button");
300 removeButton.textContent = "Remove";
301 removeButton.onclick = removeNode;
302 node.appendChild(removeButton);
303 return node;
304 }
305
306 function statementNode() {
307 var node = document.createElement("div");
308 node.setAttribute('class','head');
309 node.setAttribute('name','statement-node');
310 var nodeTitle = document.createElement("span");
311 nodeTitle.textContent = "Statement";
312 var attributes = document.createElement("div");
313 attributes.setAttribute('class','attrib');
314 var statement = attributePair("Statement:","text",false);
315 statement[1].style.width = "500px";
316 node.appendChild(nodeTitle);
317 statement.forEach(function(item){attributes.appendChild(item);},false);
318 node.appendChild(attributes);
319
320 var removeButton = document.createElement("button");
321 removeButton.textContent = "Remove";
322 removeButton.onclick = removeNode;
323 node.appendChild(removeButton);
324 return node;
325 }
326
327 function audioHolderNode() {
328 var audioHolderCounts = document.getElementsByName("audio-holder").length;
329 var node = document.createElement("div");
330 node.setAttribute("class","head");
331 node.setAttribute("name","audio-holder");
332 node.setAttribute("id","audio-holder-"+audioHolderCounts);
333 var nodeTitle = document.createElement("span");
334 nodeTitle.textContent = "Audio Holder "+(audioHolderCounts+1);
335
336 var attributes = document.createElement("div");
337 attributes.setAttribute('class','attrib');
338 var id = attributePair("ID:","text",true);
339 id[1].value=audioHolderCounts;
340 var hostURL = attributePair("Host URL:", "text",false);
341 var sampleRate = attributePair("Sample Rate:","text",false);
342 var randomiseOrder = attributePair("Randomise Element Order:","checkbox");
343 var repeatCount = attributePair("Repeat Page Count:","number");
344 repeatCount[1].value = 0;
345 var loop = attributePair("Loop Element Playback","checkbox");
346 var elementComments = attributePair("Enable Comment Boxes","checkbox");
347 id.forEach(function(item){attributes.appendChild(item);},false);
348 hostURL.forEach(function(item){attributes.appendChild(item);},false);
349 sampleRate.forEach(function(item){attributes.appendChild(item);},false);
350 hostURL.forEach(function(item){attributes.appendChild(item);},false);
351 randomiseOrder.forEach(function(item){attributes.appendChild(item);},false);
352 repeatCount.forEach(function(item){attributes.appendChild(item);},false);
353 loop.forEach(function(item){attributes.appendChild(item);},false);
354 elementComments.forEach(function(item){attributes.appendChild(item);},false);
355
356 node.appendChild(nodeTitle);
357 node.appendChild(attributes);
358
359 var pretest = document.createElement("div");
360 pretest.setAttribute('class','head');
361 pretest.setAttribute('name','pre-test');
362 var pretestTitle = document.createElement("h4");
363 pretestTitle.textContent = "Pre Test";
364 var buttonAddQ = document.createElement("button");
365 buttonAddQ.textContent = "Add Pre Test Question";
366 buttonAddQ.onclick = function(){event.srcElement.parentElement.appendChild(questionNode());};
367 var buttonAddS = document.createElement("button");
368 buttonAddS.textContent = "Add Pre Test Statement";
369 buttonAddS.onclick = function(){event.srcElement.parentElement.appendChild(statementNode());};
370 pretest.appendChild(pretestTitle);
371 pretest.appendChild(buttonAddQ);
372 pretest.appendChild(buttonAddS);
373
374 var posttest = document.createElement("div");
375 posttest.setAttribute('class','head');
376 posttest.setAttribute('name','post-test');
377 var posttestTitle = document.createElement("h4");
378 posttestTitle.textContent = "Post Test";
379 var buttonAddQ = document.createElement("button");
380 buttonAddQ.textContent = "Add Post Test Question";
381 buttonAddQ.onclick = function(){event.srcElement.parentElement.appendChild(questionNode());};
382 var buttonAddS = document.createElement("button");
383 buttonAddS.textContent = "Add Post Test Statement";
384 buttonAddS.onclick = function(){event.srcElement.parentElement.appendChild(statementNode());};
385 posttest.appendChild(posttestTitle);
386 posttest.appendChild(buttonAddQ);
387 posttest.appendChild(buttonAddS);
388
389 node.appendChild(pretest);
390 node.appendChild(posttest);
391
392 var newAudioElementButton = document.createElement("button");
393 newAudioElementButton.textContent = "Add audio element";
394 newAudioElementButton.onclick = function(){
395 event.srcElement.parentElement.appendChild(audioElementNode());
396 }; 572 };
397 node.appendChild(newAudioElementButton); 573
398 574 this.metricNode = function(name) {
399 var newCommentButton = document.createElement("button"); 575 this.enabled = name;
400 newCommentButton.textContent = "Add Comment Box";
401 newCommentButton.onclick = function() {
402 event.srcElement.parentElement.appendChild(commentBox());
403 }; 576 };
404 node.appendChild(newCommentButton); 577
405 578 this.audioHolderNode = function(parent,xml) {
406 var newInterface = document.createElement("button"); 579 this.type = 'audioHolder';
407 newInterface.textContent = "Add Interface"; 580 this.presentedId = parent.audioHolders.length;
408 newInterface.onclick = function() { 581 this.interfaceNode = function(DOM) {
409 event.srcElement.parentElement.appendChild(interfaceNode()); 582 var title = DOM.getElementsByTagName('title');
583 if (title.length == 0) {this.title = null;}
584 else {this.title = title[0].textContent;}
585 this.options = parent.commonInterface.options;
586 var scale = DOM.getElementsByTagName('scale');
587 this.scale = [];
588 for (var i=0; i<scale.length; i++) {
589 var arr = [null, null];
590 arr[0] = scale[i].getAttribute('position');
591 arr[1] = scale[i].textContent;
592 this.scale.push(arr);
593 }
594 };
595
596 this.audioElementNode = function(parent,xml) {
597 this.url = xml.getAttribute('url');
598 this.id = xml.id;
599 this.parent = parent;
600 this.type = xml.getAttribute('type');
601 if (this.type == null) {this.type = "normal";}
602 if (this.type == 'anchor') {this.anchor = true;}
603 else {this.anchor = false;}
604 if (this.type == 'reference') {this.reference = true;}
605 else {this.reference = false;}
606
607 this.marker = xml.getAttribute('marker');
608 if (this.marker == null) {this.marker = undefined;}
609
610 if (this.anchor == true) {
611 if (this.marker != undefined) {this.enforce = true;}
612 else {this.enforce = enforceAnchor;}
613 this.marker = anchor;
614 }
615 else if (this.reference == true) {
616 if (this.marker != undefined) {this.enforce = true;}
617 else {this.enforce = enforceReference;}
618 this.marker = reference;
619 }
620
621 if (this.marker != undefined) {
622 this.marker = Number(this.marker);
623 if (this.marker > 1) {this.marker /= 100;}
624 }
625 };
626
627 this.commentQuestionNode = function(xml) {
628 this.childOption = function(element) {
629 this.type = 'option';
630 this.name = element.getAttribute('name');
631 this.text = element.textContent;
632 };
633 this.id = xml.id;
634 if (xml.getAttribute('mandatory') == 'true') {this.mandatory = true;}
635 else {this.mandatory = false;}
636 this.type = xml.getAttribute('type');
637 if (this.type == undefined) {this.type = 'text';}
638 switch (this.type) {
639 case 'text':
640 this.question = xml.textContent;
641 break;
642 case 'radio':
643 var child = xml.firstElementChild;
644 this.options = [];
645 while (child != undefined) {
646 if (child.nodeName == 'statement' && this.statement == undefined) {
647 this.statement = child.textContent;
648 } else if (child.nodeName == 'option') {
649 this.options.push(new this.childOption(child));
650 }
651 child = child.nextElementSibling;
652 }
653 break;
654 case 'checkbox':
655 var child = xml.firstElementChild;
656 this.options = [];
657 while (child != undefined) {
658 if (child.nodeName == 'statement' && this.statement == undefined) {
659 this.statement = child.textContent;
660 } else if (child.nodeName == 'option') {
661 this.options.push(new this.childOption(child));
662 }
663 child = child.nextElementSibling;
664 }
665 break;
666 }
667 };
668
669 this.id = xml.id;
670 this.hostURL = xml.getAttribute('hostURL');
671 this.sampleRate = xml.getAttribute('sampleRate');
672 if (xml.getAttribute('randomiseOrder') == "true") {this.randomiseOrder = true;}
673 else {this.randomiseOrder = false;}
674 this.repeatCount = xml.getAttribute('repeatCount');
675 if (xml.getAttribute('loop') == 'true') {this.loop = true;}
676 else {this.loop == false;}
677 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;}
678 else {this.elementComments = false;}
679
680 var anchor = xml.getElementsByTagName('anchor');
681 var enforceAnchor = false;
682 if (anchor.length == 0) {
683 // Find anchor in commonInterface;
684 for (var i=0; i<parent.commonInterface.options.length; i++) {
685 if(parent.commonInterface.options[i].type == 'anchor') {
686 anchor = parent.commonInterface.options[i].value;
687 enforceAnchor = parent.commonInterface.options[i].enforce;
688 break;
689 }
690 }
691 if (typeof(anchor) == "object") {
692 anchor = null;
693 }
694 } else {
695 anchor = anchor[0].textContent;
696 }
697
698 var reference = xml.getElementsByTagName('anchor');
699 var enforceReference = false;
700 if (reference.length == 0) {
701 // Find anchor in commonInterface;
702 for (var i=0; i<parent.commonInterface.options.length; i++) {
703 if(parent.commonInterface.options[i].type == 'reference') {
704 reference = parent.commonInterface.options[i].value;
705 enforceReference = parent.commonInterface.options[i].enforce;
706 break;
707 }
708 }
709 if (typeof(reference) == "object") {
710 reference = null;
711 }
712 } else {
713 reference = reference[0].textContent;
714 }
715
716 if (typeof(anchor) == 'number') {
717 if (anchor > 1 && anchor < 100) {anchor /= 100.0;}
718 }
719
720 if (typeof(reference) == 'number') {
721 if (reference > 1 && reference < 100) {reference /= 100.0;}
722 }
723
724 this.preTest = new parent.prepostNode('pretest',xml.getElementsByTagName('PreTest'));
725 this.postTest = new parent.prepostNode('posttest',xml.getElementsByTagName('PostTest'));
726
727 this.interfaces = [];
728 var interfaceDOM = xml.getElementsByTagName('interface');
729 for (var i=0; i<interfaceDOM.length; i++) {
730 this.interfaces.push(new this.interfaceNode(interfaceDOM[i]));
731 }
732
733 this.commentBoxPrefix = xml.getElementsByTagName('commentBoxPrefix');
734 if (this.commentBoxPrefix.length != 0) {
735 this.commentBoxPrefix = this.commentBoxPrefix[0].textContent;
736 } else {
737 this.commentBoxPrefix = "Comment on track";
738 }
739
740 this.audioElements =[];
741 var audioElementsDOM = xml.getElementsByTagName('audioElements');
742 this.outsideReference = null;
743 for (var i=0; i<audioElementsDOM.length; i++) {
744 if (audioElementsDOM[i].getAttribute('type') == 'outsidereference') {
745 if (this.outsideReference == null) {
746 this.outsideReference = new this.audioElementNode(this,audioElementsDOM[i]);
747 } else {
748 console.log('Error only one audioelement can be of type outsidereference per audioholder');
749 this.audioElements.push(new this.audioElementNode(this,audioElementsDOM[i]));
750 console.log('Element id '+audioElementsDOM[i].id+' made into normal node');
751 }
752 } else {
753 this.audioElements.push(new this.audioElementNode(this,audioElementsDOM[i]));
754 }
755 }
756
757 if (this.randomiseOrder) {
758 this.audioElements = randomiseOrder(this.audioElements);
759 }
760
761 // Check only one anchor and one reference per audioNode
762 var anchor = [];
763 var reference = [];
764 this.anchorId = null;
765 this.referenceId = null;
766 for (var i=0; i<this.audioElements.length; i++)
767 {
768 if (this.audioElements[i].anchor == true) {anchor.push(i);}
769 if (this.audioElements[i].reference == true) {reference.push(i);}
770 }
771
772 if (anchor.length > 1) {
773 console.log('Error - cannot have more than one anchor!');
774 console.log('Each anchor node will be a normal mode to continue the test');
775 for (var i=0; i<anchor.length; i++)
776 {
777 this.audioElements[anchor[i]].anchor = false;
778 this.audioElements[anchor[i]].value = undefined;
779 }
780 } else {this.anchorId = anchor[0];}
781 if (reference.length > 1) {
782 console.log('Error - cannot have more than one anchor!');
783 console.log('Each anchor node will be a normal mode to continue the test');
784 for (var i=0; i<reference.length; i++)
785 {
786 this.audioElements[reference[i]].reference = false;
787 this.audioElements[reference[i]].value = undefined;
788 }
789 } else {this.referenceId = reference[0];}
790
791 this.commentQuestions = [];
792 var commentQuestionsDOM = xml.getElementsByTagName('CommentQuestion');
793 for (var i=0; i<commentQuestionsDOM.length; i++) {
794 this.commentQuestions.push(new this.commentQuestionNode(commentQuestionsDOM[i]));
795 }
410 }; 796 };
411 node.appendChild(newInterface);
412
413 var removeButton = document.createElement("button");
414 removeButton.textContent = "Remove Audio Holder";
415 removeButton.onclick = removeNode;
416 node.appendChild(removeButton);
417 return node;
418 }
419
420 function audioElementNode() {
421 var node = document.createElement('div');
422 node.setAttribute('class','head');
423 node.setAttribute('name','audio-element');
424 var nodeTitle = document.createElement('span');
425 nodeTitle.textContent = 'Audio Element';
426
427 var attributes = document.createElement("div");
428 attributes.setAttribute('class','attrib');
429 var id = attributePair("ID:","text",true);
430 var url = attributePair("URL:","text",true);
431 id.forEach(function(item){attributes.appendChild(item);},false);
432 url.forEach(function(item){attributes.appendChild(item);},false);
433
434 node.appendChild(nodeTitle);
435 node.appendChild(attributes);
436
437 var removeButton = document.createElement("button");
438 removeButton.textContent = "Remove Audio Element";
439 removeButton.onclick = removeNode;
440 node.appendChild(removeButton);
441 return node;
442 }
443
444 function commentBox() {
445 var node = document.createElement('div');
446 node.setAttribute('class','head');
447 node.setAttribute('name','comment-question');
448 var nodeTitle = document.createElement('h4');
449 nodeTitle.textContent = "Comment Box";
450
451 var attributes = document.createElement('div');
452 attributes.setAttribute('class','attrib');
453 var id = attributePair("ID:",'text',true);
454 var question = attributePair("Question:",'text',true);
455 question[1].style.width = "500px";
456 id.forEach(function(item){attributes.appendChild(item);},false);
457 question.forEach(function(item){attributes.appendChild(item);},false);
458
459 var removeButton = document.createElement("button");
460 removeButton.textContent = "Remove Comment Box";
461 removeButton.onclick = removeNode;
462
463 node.appendChild(nodeTitle);
464 node.appendChild(attributes);
465 node.appendChild(removeButton);
466 return node;
467 }
468
469 function interfaceNode() {
470 var selectedInterface = document.getElementById('interface').value;
471 var node = document.createElement('div');
472 node.setAttribute('class','head');
473 node.setAttribute('name','interface-options');
474 var nodeTitle = document.createElement('h4');
475 nodeTitle.textContent = "Interface";
476
477 var attributes = document.createElement('div');
478 attributes.setAttribute('class','attrib');
479 var title = attributePair('Title: ','text',false);
480 title[1].style.width = "500px";
481
482 var addMarker = document.createElement('button');
483 addMarker.textContent = "Add Scale Marker";
484 addMarker.onclick = function() {
485 event.srcElement.parentElement.appendChild(newScaleMarker());
486 };
487
488 title.forEach(function(item){attributes.appendChild(item);},false);
489
490 var removeButton = document.createElement("button");
491 removeButton.textContent = "Remove Interface";
492 removeButton.onclick = removeNode;
493
494 node.appendChild(nodeTitle);
495 node.appendChild(attributes);
496 node.appendChild(addMarker);
497 node.appendChild(removeButton);
498 return node;
499 }
500
501 function newScaleMarker() {
502 var node = document.createElement('div');
503 node.setAttribute('class','head');
504 node.setAttribute('name','interface-options');
505 var nodeTitle = document.createElement('span');
506 nodeTitle.textContent = "Marker";
507 var attributes = document.createElement('div');
508 attributes.setAttribute('class','attrib');
509 var text = attributePair('Text: ','text',true);
510 var position = attributePair('Positon','number',true);
511
512 text.forEach(function(item){attributes.appendChild(item);},false);
513 position.forEach(function(item){attributes.appendChild(item);},false);
514
515 var removeButton = document.createElement("button");
516 removeButton.textContent = "Remove Marker";
517 removeButton.onclick = removeNode;
518
519 node.appendChild(nodeTitle);
520 node.appendChild(attributes);
521 node.appendChild(removeButton);
522 return node;
523 }
524
525 function handleDragOver(e) {
526 e.stopPropagation();
527 e.preventDefault();
528 }
529 function handleDragEnter(e) {
530 e.stopPropagation();
531 e.preventDefault();
532 this.style.backgroundColor = '#AAFFAA';
533 }
534 function handleDragLeave(e) {
535 e.stopPropagation();
536 e.preventDefault();
537 this.style.backgroundColor = "#FFFFFF";
538 }
539 function handleDrop(e) {
540 e.stopPropagation();
541 e.preventDefault();
542
543 var file = e.dataTransfer.files[0];
544
545 // Uses HTML5 FileAPI - https://w3c.github.io/FileAPI/#filereader-interface
546 var reader = new FileReader();
547 reader.onload = function() {
548 var parse = new DOMParser();
549 var xml = parse.parseFromString(reader.result,'text/xml');
550 importXML(xml);
551 };
552 reader.readAsText(file);
553
554 }
555 var g_XML;
556
557 function importXML(xml) {
558 g_XML = xml;
559
560 var root = xml.getElementsByTagName('BrowserEvalProjectDocument')[0];
561 var setup = xml.getElementsByTagName('setup')[0];
562 document.getElementById('interface').value = setup.getAttribute('interface');
563 document.getElementById('projectReturn').value = setup.getAttribute('projectReturn');
564 document.getElementById('randomisePageOrder').checked = setup.getAttribute('randomiseOrder');
565 document.getElementById('collectMetrics').checked = setup.getAttribute('collectMetrics');
566
567 var globalPreTest = setup.getElementsByTagName('PreTest')[0];
568 var globalPostTest = setup.getElementsByTagName('PostTest')[0];
569 for (var i=0; i<globalPreTest.childElementCount; i++) {
570 var child = globalPreTest.children[i];
571 var node;
572 if (child.nodeName == "question") {
573 node = questionNode();
574 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
575 attribs[0].value = child.id;
576 attribs[1].value = child.textContent;
577 attribs[2].checked = child.getAttribute('mandatory');
578 } else if (child.nodeName == "statement") {
579 node = statementNode();
580 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
581 attribs[0].value = child.textContent;
582 }
583 document.getElementById('globalPreTest').appendChild(node);
584 }
585
586 for (var i=0; i<globalPostTest.childElementCount; i++) {
587 var child = globalPostTest.children[i];
588 var node;
589 if (child.nodeName == "question") {
590 node = questionNode();
591 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
592 attribs[0].value = child.id;
593 attribs[1].value = child.textContent;
594 attribs[2].checked = child.getAttribute('mandatory');
595 } else if (child.nodeName == "statement") {
596 node = statementNode();
597 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
598 attribs[0].value = child.textContent;
599 }
600 document.getElementById('globalPostTest').appendChild(node);
601 }
602
603 // Metric Enable Flags
604 var mEnable = setup.getElementsByTagName('Metric')[0].getElementsByTagName('metricEnable');
605 for (var i=0; i<mEnable.length; i++) {
606 var node = mEnable[i];
607 var enabled = node.textContent;
608 document.getElementById(enabled).checked = true;
609 }
610
611 var audioHolders = root.getElementsByTagName('audioHolder');
612 for (var i=0; i<audioHolders.length; i++) {
613 var audioHolderDOM = audioHolderNode();
614 var attribs = audioHolderDOM.getElementsByClassName('attrib')[0].getElementsByTagName('input');
615 attribs[0].value = audioHolders[i].id;
616 attribs[1].value = audioHolders[i].getAttribute('sampleRate');
617 attribs[2].value = audioHolders[i].getAttribute('hostURL');
618 attribs[3].checked = audioHolders[i].getAttribute('randomiseOrder');
619 attribs[4].value = audioHolders[i].getAttribute('repeatCount');
620 attribs[5].checked = audioHolders[i].getAttribute('loop');
621 attribs[6].checked = audioHolders[i].getAttribute('elementComments');
622
623 var PreTest = audioHolders[i].getElementsByTagName('PreTest');
624 var PostTest = audioHolders[i].getElementsByTagName('PostTest');
625 if (PreTest.length != 0) {
626 PreTest = PreTest[0];
627 for (var j=0; j<PreTest.childElementCount; j++) {
628 var child = PreTest.children[j];
629 var node;
630 if (child.nodeName == "question") {
631 node = questionNode();
632 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
633 attribs[0].value = child.id;
634 attribs[1].value = child.textContent;
635 attribs[2].checked = child.getAttribute('mandatory');
636 } else if (child.nodeName == "statement") {
637 node = statementNode();
638 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
639 attribs[0].value = child.textContent;
640 }
641 audioHolderDOM.children[2].appendChild(node);
642 }
643 }
644 if (PostTest.length != 0) {
645 PostTest = PostTest[0];
646 for (var j=0; j<PostTest.childElementCount; j++) {
647 var child = PostTest.children[j];
648 var node;
649 if (child.nodeName == "question") {
650 node = questionNode();
651 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
652 attribs[0].value = child.id;
653 attribs[1].value = child.textContent;
654 attribs[2].checked = child.getAttribute('mandatory');
655 } else if (child.nodeName == "statement") {
656 node = statementNode();
657 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
658 attribs[0].value = child.textContent;
659 }
660 audioHolderDOM.children[3].appendChild(node);
661 }
662 }
663 // Process interface
664 var interfaceNodes = audioHolders[i].getElementsByTagName('interface');
665 for (var j=0; j<interfaceNodes.length; j++) {
666 var node = interfaceNode();
667 var child = interfaceNodes[j];
668 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
669 attribs[0].value = child.getElementsByTagName('title')[0].textContent;
670
671 var markers = child.getElementsByTagName('scale');
672 for (var k=0; k<markers.length; k++) {
673 var markerNode = newScaleMarker();
674 attribs = markerNode.getElementsByClassName('attrib')[0].getElementsByTagName('input');
675 attribs[0].value = markers[k].textContent;
676 attribs[1].value = markers[k].getAttribute('position');
677 node.appendChild(markerNode);
678 }
679 audioHolderDOM.appendChild(node);
680 }
681
682
683 // Process audio-element
684 var audioElements = audioHolders[i].getElementsByTagName('audioElements');
685 for (var j=0; j<audioElements.length; j++) {
686 var node = audioElementNode();
687 var child = audioElements[j];
688 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
689 attribs[0].value = child.id;
690 attribs[1].value = child.getAttribute('url');
691 audioHolderDOM.appendChild(node);
692 }
693
694 // Process comment-question
695 var commentQuestion = audioHolders[0].getElementsByTagName('CommentQuestion');
696 for (var j=0; j<commentQuestion.length; j++) {
697 var node = commentBox();
698 var child = commentQuestion[j];
699 var attribs = node.getElementsByClassName('attrib')[0].getElementsByTagName('input');
700 attribs[0].value = child.id;
701 attribs[1].value = child.textContent;
702 audioHolderDOM.appendChild(node);
703 }
704
705 document.getElementById('setup').appendChild(audioHolderDOM);
706 }
707 } 797 }
708 </script> 798 </script>
709 <style> 799 <style>
710 div { 800 div.popup {
711 padding: 2px; 801 width: 500px;
712 margin-top: 2px; 802 position: absolute;
713 margin-bottom: 2px; 803 height: 400px;
804 background-color: #fff;
805 border-radius: 10px;
806 box-shadow: 0px 0px 50px #000;
807 z-index: 2;
714 } 808 }
715 div.head{ 809
716 margin-left: 10px; 810 button.popupButton {
717 border: black; 811 /* Button for popup window
812 */
813 min-width: 50px;
814 height: 25px;
815 position: relative;
816 border-radius: 5px;
817 border: #444;
818 border-width: 1px;
819 border-style: solid;
820 background-color: #fff;
821 }
822
823 div.dragndrop {
824 margin-top: 10px;
825 border:#000000;
826 border-style: dashed;
718 border-width: 2px; 827 border-width: 2px;
719 border-style: solid;
720 } 828 }
721 div.attrib{ 829 div.dndheaderelement {
722 margin-left:25px; 830 float: left;
723 border: black; 831 height: 100%;
724 border-width: 2px; 832 border-right: #DDDDDD;
725 border-style: dashed; 833 border-right-width: 1px;
726 margin-bottom: 10px; 834 border-right-style: solid;
727 } 835 }
728 div#dragFile{ 836 div.dndheaderelement span{
729 height:100px; 837 padding-left: 5px;
730 border-width: 2px;
731 border-style: dashed;
732 margin-bottom: 10px;
733 } 838 }
734 </style> 839 </style>
735
736 </head> 840 </head>
737 841
738 <body> 842 <body>
739 <h1>Create Test Setup XML</h1> 843 <div id="content"></div>
740 <div id="dragFile">
741 <span>Drag and Drop an XML specification file here to auto-load.</span>
742 </div>
743 <button id="validateXML" onclick="buttonClickedValidate();">Validate</button>
744 <button id="createXML" onclick="buttonClickedSubmit();" disabled>Submit</button>
745 <span id="errorMessage" visibility="hidden"></span>
746 <div id="topLevelBody" align="left">
747 <!-- Interface goes here -->
748 <div name='test-setup'>
749 <div id="setup" class="head">
750 <h2>Setup Tag</h2>
751 <div id="setup-attribs" class="attrib">
752 <span>Interface</span>
753 <select id="interface">
754 <option value='APE'>APE</option>
755 </select>
756 <span>Project Return</span>
757 <input type="text" id="projectReturn" mandatory="false">
758 <span>Randomise Test Page Order</span>
759 <input id="randomisePageOrder" type="checkbox" value="false">
760 <span>Collect Session Metrics</span>
761 <input id="collectMetrics" type="checkbox">
762 </div>
763 <div id="globalPreTest" class="head">
764 <h3>Pre Test</h3>
765 <button id="addPreTestQ" onclick="event.srcElement.parentElement.appendChild(questionNode());">Add Pre Test Question</button>
766 <button id="addPreTestS" onclick="event.srcElement.parentElement.appendChild(statementNode());">Add Pre Test Statement</button>
767 </div>
768 <div id="globalPostTest" class="head">
769 <h3>Post Test</h3>
770 <button id="addPreTestQ" onclick="event.srcElement.parentElement.appendChild(questionNode());">Add Post Test Question</button>
771 <button id="addPreTestS" onclick="event.srcElement.parentElement.appendChild(statementNode());">Add Post Test Statement</button>
772 </div>
773 <div id="globalMetric" class="head">
774 <h3>Global Metrics</h3>
775 <div id="globalMetric-attrib" class="attrib">
776 <span>Test Timer</span>
777 <input type="checkbox" id="testTimer" />
778 <span>Element Playback Timer</span>
779 <input type="checkbox" id="elementTimer" />
780 <span>Element Initial Position</span>
781 <input type="checkbox" id="elementInitialPosition" />
782 <span>Element Tracker</span>
783 <input type="checkbox" id="elementTracker" />
784 <span>Element Listen Tracker</span>
785 <input type="checkbox" id="elementListenTracker" />
786 <span>Element Flag Listened To</span>
787 <input type="checkbox" id="elementFlagListenedTo" />
788 <span>Element Flag Moved</span>
789 <input type="checkbox" id="elementFlagMoved" />
790 </div>
791 </div>
792 <button id="addAudioHolder" onclick="event.srcElement.parentElement.appendChild(audioHolderNode());">Add AudioHolder / Test Page</button>
793 </div>
794 </div>
795 </div>
796 </body> 844 </body>
797 </html> 845 </html>