comparison test_create/test_create.html @ 1370:f329347e8918

New test creator tool. Still WIP, but much more dynamic. Based on XSD and external lists so far easier to modify.
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Wed, 10 Feb 2016 12:02:25 +0000
parents 279930a008ca
children e3b16bb23a50
comparison
equal deleted inserted replaced
1369:ebe6c10bd52d 1370:f329347e8918
1 <!DOCTYPE html> 1 <html>
2 <html lang="en"> 2 <head>
3 <head> 3 <!-- This defines the test creator tool for the Web Audio Evaluation Toolbox -->
4 <meta charset="utf-8"> 4 <link rel='stylesheet' type="text/css" href="style.css"/>
5 5 <script type="text/javascript">
6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame 6 // Copy of Specifiation node from Core.js
7 Remove this if you use the .htaccess --> 7 function Specification() {
8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 8 // Handles the decoding of the project specification XML into a simple JavaScript Object.
9 9
10 <title>WAET: Test Creator</title> 10 this.interface = null;
11 11 this.projectReturn = null;
12 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 12 this.randomiseOrder = null;
13 <script type="text/javascript"> 13 this.testPages = null;
14 14 this.pages = [];
15 var APEInterfaceOptions = [["playhead","page-count"],["Show the playhead/scrubber bar", "Show test page count"]]; 15 this.metrics = null;
16 var APEInterfaceChecks = [["fragmentPlayed","fragmentFullPlayback","fragmentMoved","fragmentComments"],["All Fragments Played","All Fragments Played in entirety","All sliders moved","All fragments have comments"]]; 16 this.interfaces = null;
17 var APEInterfaceMetrics = [["testTimer","elementTimer","elementTracker","elementTrackerFull","elementFlagListenedTo","elementFlagMoved","elementFlagComments"],["Test Duration","Total time each fragment was listened to","Return initialised position of marker","Fragment movement tracker with timestamps","Flag if fragment listened to","Flag if fragment moved","Flag if fragment has comments"]]; 17 this.loudness = null;
18 var MUSHRAInterfaceOptions = [[],[]]; 18 this.errors = [];
19 var MUSHRAInterfaceChecks = [["fragmentPlayed","fragmentMoved","fragmentComments"],["All Fragments Played","All sliders moved","All fragments have comments"]]; 19 this.schema = null;
20 var MUSHRAInterfaceMetrics = [["testTimer","elementTimer","elementTracker","elementTrackerFull","elementFlagListenedTo","elementFlagMoved","elementFlagComments"],["Test Duration","Total time each fragment was listened to","Return initialised position of marker","Fragment movement tracker with timestamps","Flag if fragment listened to","Flag if fragment moved","Flag if fragment has comments"]]; 20
21 var popupInstance; 21 this.randomiseOrder = function(input)
22 var specificationNode; 22 {
23 var audioContext; 23 // This takes an array of information and randomises the order
24 var audioObjects = []; 24 var N = input.length;
25 window.onload = function() 25
26 { 26 var inputSequence = []; // For safety purposes: keep track of randomisation
27 var AudioContext = window.AudioContext || window.webkitAudioContext; 27 for (var counter = 0; counter < N; ++counter)
28 audioContext = new AudioContext; 28 inputSequence.push(counter) // Fill array
29 popupInstance = new popup(); 29 var inputSequenceClone = inputSequence.slice(0);
30 popupInstance.advanceState(); 30
31 specificationNode = new Specification(); 31 var holdArr = [];
32 specificationNode.projectReturn = "null"; 32 var outputSequence = [];
33 }; 33 for (var n=0; n<N; n++)
34 34 {
35 function popup() 35 // First pick a random number
36 { 36 var r = Math.random();
37 var x = window.innerWidth; 37 // Multiply and floor by the number of elements left
38 var y = window.innerHeight; 38 r = Math.floor(r*input.length);
39 this.popupHolder = document.createElement('div'); 39 // Pick out that element and delete from the array
40 this.popupHolder.style.visibility = 'hidden'; 40 holdArr.push(input.splice(r,1)[0]);
41 this.popupContent = document.createElement('div'); 41 // Do the same with sequence
42 this.popupTitle = document.createElement('div'); 42 outputSequence.push(inputSequence.splice(r,1)[0]);
43 this.popupBody = document.createElement('div'); 43 }
44 this.popupFooter = document.createElement('div'); 44 console.log(inputSequenceClone.toString()); // print original array to console
45 this.popupTitleText = document.createElement('span'); 45 console.log(outputSequence.toString()); // print randomised array to console
46 this.popupTitle.appendChild(this.popupTitleText); 46 return holdArr;
47 47 };
48 this.popupHolder.className = "popup"; 48
49 this.popupHolder.style.left = (x-500)/2 +'px'; 49 this.processAttribute = function(attribute,schema)
50 this.popupHolder.style.top = (y-400)/2 + 'px'; 50 {
51 this.popupContent.style.padding = "20px"; 51 // attribute is the string returned from getAttribute on the XML
52 this.popupHolder.appendChild(this.popupContent); 52 // schema is the <xs:attribute> node
53 53 if (schema.getAttribute('name') == undefined && schema.getAttribute('ref') != undefined)
54 this.popupTitle.style.width = "100%"; 54 {
55 this.popupTitle.style.height = "50px"; 55 schema = this.schema.getAllElementsByName(schema.getAttribute('ref'))[0];
56 this.popupTitle.style.fontSize = "xx-large"; 56 }
57 this.popupContent.appendChild(this.popupTitle); 57 var defaultOpt = schema.getAttribute('default');
58 58 if (attribute == null) {
59 this.popupBody.style.width = "100%"; 59 attribute = defaultOpt;
60 this.popupBody.style.height = "280px"; 60 }
61 this.popupContent.appendChild(this.popupBody); 61 var dataType = schema.getAttribute('type');
62 62 if (typeof dataType == "string") { dataType = dataType.substr(3);}
63 this.popupFooter.style.width = "100%"; 63 else {dataType = "string";}
64 this.popupFooter.style.height = "30px"; 64 if (attribute == null)
65 this.popupContent.appendChild(this.popupFooter); 65 {
66 var body = document.getElementsByTagName('body')[0]; 66 return attribute;
67 body.appendChild(this.popupHolder); 67 }
68 68 switch(dataType)
69 this.pageBlank = document.createElement('div'); 69 {
70 body.appendChild(this.pageBlank); 70 case "boolean":
71 this.pageBlank.style.width = "100%"; 71 if (attribute == 'true'){attribute = true;}else{attribute=false;}
72 this.pageBlank.style.height = "100%"; 72 break;
73 this.pageBlank.style.position = "absolute"; 73 case "negativeInteger":
74 this.pageBlank.style.left = "0px"; 74 case "positiveInteger":
75 this.pageBlank.style.top = "0px"; 75 case "nonNegativeInteger":
76 this.pageBlank.style.backgroundColor = "rgba(0,0,0,0.5)"; 76 case "nonPositiveInteger":
77 this.pageBlank.style.visibility = 'hidden'; 77 case "integer":
78 78 case "decimal":
79 this.state = 0; 79 case "short":
80 this.dataTransfer = null; 80 attribute = Number(attribute);
81 81 break;
82 this.showPopup = function() 82 case "string":
83 { 83 default:
84 this.popupHolder.style.visibility = 'visible'; 84 attribute = String(attribute);
85 this.popupHolder.style.zIndex = "3"; 85 break;
86 this.pageBlank.style.visibility = 'visible'; 86 }
87 this.pageBlank.style.zIndex = "2"; 87 return attribute;
88 }; 88 };
89 89
90 this.hidePopup = function() 90 this.decode = function(projectXML) {
91 { 91 this.errors = [];
92 this.popupHolder.style.visibility = 'hidden'; 92 // projectXML - DOM Parsed document
93 this.popupHolder.style.zIndex = "-1"; 93 this.projectXML = projectXML.childNodes[0];
94 this.pageBlank.style.visibility = 'hidden'; 94 var setupNode = projectXML.getElementsByTagName('setup')[0];
95 this.pageBlank.style.zIndex = "-2"; 95 var schemaSetup = this.schema.getAllElementsByName('setup')[0];
96 }; 96 // First decode the attributes
97 97 var attributes = schemaSetup.getAllElementsByTagName('xs:attribute');
98 this.init = function() 98 for (var i in attributes)
99 { 99 {
100 this.popupTitleText.textContent = "Welcome"; 100 if (isNaN(Number(i)) == true){break;}
101 var text = document.createElement('span'); 101 var attributeName = attributes[i].getAttribute('name');
102 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"; 102 var projectAttr = setupNode.getAttribute(attributeName);
103 var dnd = document.createElement('div'); 103 projectAttr = this.processAttribute(projectAttr,attributes[i]);
104 dnd.style.width = "100%"; 104 switch(typeof projectAttr)
105 dnd.style.height = "50px"; 105 {
106 dnd.className = "dragndrop"; 106 case "number":
107 dnd.ondragover = function(e) { 107 case "boolean":
108 e.stopPropagation(); 108 eval('this.'+attributeName+' = '+projectAttr);
109 e.preventDefault(); 109 break;
110 }; 110 case "string":
111 dnd.ondragenter = function(e) { 111 eval('this.'+attributeName+' = "'+projectAttr+'"');
112 e.stopPropagation(); 112 break;
113 e.preventDefault(); 113 }
114 this.style.backgroundColor = '#AAFFAA'; 114
115 }; 115 }
116 dnd.ondragleave = function(e) { 116
117 e.stopPropagation(); 117 this.metrics = new this.metricNode();
118 e.preventDefault(); 118
119 this.style.backgroundColor = "#FFFFFF"; 119 this.metrics.decode(this,setupNode.getElementsByTagName('metric')[0]);
120 }; 120
121 dnd.ondrop = function(e) { 121 // Now process the survey node options
122 e.stopPropagation(); 122 var survey = setupNode.getElementsByTagName('survey');
123 e.preventDefault(); 123 for (var i in survey) {
124 124 if (isNaN(Number(i)) == true){break;}
125 var file = e.dataTransfer.files[0]; 125 var location = survey[i].getAttribute('location');
126 126 if (location == 'pre' || location == 'before')
127 // Uses HTML5 FileAPI - https://w3c.github.io/FileAPI/#filereader-interface 127 {
128 var reader = new FileReader(); 128 if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");}
129 reader.onload = function() { 129 else {
130 var parse = new DOMParser(); 130 this.preTest = new this.surveyNode();
131 var xml = parse.parseFromString(reader.result,'text/xml'); 131 this.preTest.decode(this,survey[i]);
132 specificationNode.decode(xml); 132 }
133 popupInstance.hidePopup(); 133 } else if (location == 'post' || location == 'after') {
134 SpecificationToHTML(); 134 if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");}
135 }; 135 else {
136 reader.readAsText(file); 136 this.postTest = new this.surveyNode();
137 137 this.postTest.decode(this,survey[i]);
138 }; 138 }
139 this.popupBody.appendChild(text); 139 }
140 this.popupBody.appendChild(dnd); 140 }
141 this.showPopup(); 141
142 142 var interfaceNode = setupNode.getElementsByTagName('interface');
143 var button = document.createElement('button'); 143 if (interfaceNode.length > 1)
144 button.className = "popupButton"; 144 {
145 button.textContent = "New File"; 145 this.errors.push("Only one <interface> node in the <setup> node allowed! Others except first ingnored!");
146 button.onclick = function(event) { 146 }
147 popupInstance.advanceState(); 147 this.interfaces = new this.interfaceNode();
148 }; 148 if (interfaceNode.length != 0)
149 this.popupFooter.appendChild(button); 149 {
150 }; 150 interfaceNode = interfaceNode[0];
151 151 this.interfaces.decode(this,interfaceNode,this.schema.getAllElementsByName('interface')[1]);
152 this.advanceState = function() 152 }
153 { 153
154 this.popupBody.innerHTML = null; 154 // Page tags
155 this.popupFooter.innerHTML = null; 155 var pageTags = projectXML.getElementsByTagName('page');
156 this.popupTitleText.textContent = null; 156 var pageSchema = this.schema.getAllElementsByName('page')[0];
157 switch(this.state) 157 for (var i=0; i<pageTags.length; i++)
158 { 158 {
159 case 0: 159 var node = new this.page();
160 this.init(); 160 node.decode(this,pageTags[i],pageSchema);
161 break; 161 this.pages.push(node);
162 case 1: 162 }
163 this.popupTitleText.textContent = "Test Type"; 163 };
164 var text = document.createElement("span"); 164
165 text.textContent = "What type of test would you like to use. Currently APE (Audio Perceptual Evaluation) and MUSHRA style interfaces are available"; 165 this.encode = function()
166 this.popupBody.appendChild(text); 166 {
167 var select = document.createElement("select"); 167 var root = document.implementation.createDocument(null,"waet");
168 select.id="interface-select"; 168
169 var opt1 = document.createElement("option"); 169 // Build setup node
170 opt1.value = "APE"; 170
171 opt1.textContent = "APE"; 171 return root;
172 select.appendChild(opt1); 172 };
173 var opt2 = document.createElement("option"); 173
174 opt2.value = "MUSHRA"; 174 this.surveyNode = function() {
175 opt2.textContent = "MUSHRA"; 175 this.location = null;
176 select.appendChild(opt2); 176 this.options = [];
177 this.popupBody.appendChild(select); 177 this.schema = specification.schema.getAllElementsByName('survey')[0];
178 178
179 var button = document.createElement('button'); 179 this.OptionNode = function() {
180 button.className = "popupButton"; 180 this.type = undefined;
181 button.textContent = "Submit"; 181 this.schema = specification.schema.getAllElementsByName('surveyentry')[0];
182 button.onclick = function(event) { 182 this.id = undefined;
183 var select = document.getElementById("interface-select"); 183 this.mandatory = undefined;
184 specificationNode.interfaceType = select.value; 184 this.statement = undefined;
185 specificationNode.collectMetrics = true; 185 this.boxsize = undefined;
186 popupInstance.advanceState(); 186 this.options = [];
187 }; 187 this.min = undefined;
188 this.popupFooter.appendChild(button); 188 this.max = undefined;
189 break; 189 this.step = undefined;
190 case 2: 190
191 this.popupTitleText.textContent = "Test Options"; 191 this.decode = function(parent,child)
192 var holder = document.createElement('div'); 192 {
193 holder.style.margin = "5px"; 193 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
194 var checkbox = document.createElement('input'); 194 for (var i in attributeMap){
195 checkbox.type = 'checkbox'; 195 if(isNaN(Number(i)) == true){break;}
196 checkbox.id = "Randomise-Page"; 196 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
197 var text = document.createElement('span'); 197 var projectAttr = child.getAttribute(attributeName);
198 text.textContent = "Randomise Page Order"; 198 projectAttr = parent.processAttribute(projectAttr,attributeMap[i]);
199 holder.appendChild(checkbox); 199 switch(typeof projectAttr)
200 holder.appendChild(text); 200 {
201 this.popupBody.appendChild(holder); 201 case "number":
202 switch(specificationNode.interfaceType) 202 case "boolean":
203 { 203 eval('this.'+attributeName+' = '+projectAttr);
204 case "APE": 204 break;
205 for (var i=0; i<APEInterfaceOptions[0].length; i++) 205 case "string":
206 { 206 eval('this.'+attributeName+' = "'+projectAttr+'"');
207 holder = document.createElement('div'); 207 break;
208 holder.style.margin = "5px"; 208 }
209 checkbox = document.createElement('input'); 209 }
210 checkbox.type = 'checkbox'; 210 this.statement = child.getElementsByTagName('statement')[0].textContent;
211 checkbox.setAttribute("name","option"); 211 if (this.type == "checkbox" || this.type == "radio") {
212 checkbox.id = APEInterfaceOptions[0][i]; 212 var children = child.getElementsByTagName('option');
213 text = document.createElement('span'); 213 if (children.length == null) {
214 text.textContent = APEInterfaceOptions[1][i]; 214 console.log('Malformed' +child.nodeName+ 'entry');
215 holder.appendChild(checkbox); 215 this.statement = 'Malformed' +child.nodeName+ 'entry';
216 holder.appendChild(text); 216 this.type = 'statement';
217 this.popupBody.appendChild(holder); 217 } else {
218 } 218 this.options = [];
219 for (var i=0; i<APEInterfaceChecks[0].length; i++) 219 for (var i in children)
220 { 220 {
221 holder = document.createElement('div'); 221 if (isNaN(Number(i))==true){break;}
222 holder.style.margin = "5px"; 222 this.options.push({
223 checkbox = document.createElement('input'); 223 name: children[i].getAttribute('name'),
224 checkbox.type = 'checkbox'; 224 text: children[i].textContent
225 checkbox.setAttribute("name","check"); 225 });
226 checkbox.id = APEInterfaceChecks[0][i]; 226 }
227 text = document.createElement('span'); 227 }
228 text.textContent = APEInterfaceChecks[1][i]; 228 }
229 holder.appendChild(checkbox); 229 };
230 holder.appendChild(text); 230
231 this.popupBody.appendChild(holder); 231 this.exportXML = function(root)
232 } 232 {
233 break; 233 var node = root.createElement('surveyelement');
234 case "MUSHRA": 234 node.setAttribute('type',this.type);
235 for (var i=0; i<MUSHRAInterfaceOptions[0].length; i++) 235 var statement = root.createElement('statement');
236 { 236 statement.textContent = this.statement;
237 holder = document.createElement('div'); 237 node.appendChild(statement);
238 holder.style.margin = "5px"; 238 switch(this.type)
239 checkbox = document.createElement('input'); 239 {
240 checkbox.type = 'checkbox'; 240 case "statement":
241 checkbox.setAttribute("name","option"); 241 break;
242 checkbox.id = MUSHRAInterfaceOptions[0][i]; 242 case "question":
243 text = document.createElement('span'); 243 node.id = this.id;
244 text.textContent = MUSHRAInterfaceOptions[1][i]; 244 node.setAttribute("mandatory",this.mandatory);
245 holder.appendChild(checkbox); 245 node.setAttribute("boxsize",this.boxsize);
246 holder.appendChild(text); 246 break;
247 this.popupBody.appendChild(holder); 247 case "number":
248 } 248 node.id = this.id;
249 for (var i=0; i<MUSHRAInterfaceChecks[0].length; i++) 249 node.setAttribute("mandatory",this.mandatory);
250 { 250 node.setAttribute("min", this.min);
251 holder = document.createElement('div'); 251 node.setAttribute("max", this.max);
252 holder.style.margin = "5px"; 252 node.setAttribute("step", this.step);
253 checkbox = document.createElement('input'); 253 break;
254 checkbox.type = 'checkbox'; 254 case "checkbox":
255 checkbox.setAttribute("name","check"); 255 case "radio":
256 checkbox.id = MUSHRAInterfaceChecks[0][i]; 256 node.id = this.id;
257 text = document.createElement('span'); 257 for (var i=0; i<this.options.length; i++)
258 text.textContent = MUSHRAInterfaceChecks[1][i]; 258 {
259 holder.appendChild(checkbox); 259 var option = this.options[i];
260 holder.appendChild(text); 260 var optionNode = root.createElement("option");
261 this.popupBody.appendChild(holder); 261 optionNode.setAttribute("name",option.name);
262 } 262 optionNode.textContent = option.text;
263 } 263 node.appendChild(optionNode);
264 var button = document.createElement('button'); 264 }
265 button.className = "popupButton"; 265 break;
266 button.textContent = "Submit"; 266 }
267 button.onclick = function(event) { 267 return node;
268 var optHold = popupInstance.popupBody; 268 };
269 var opt = optHold.firstChild; 269 };
270 var input = opt.getElementsByTagName('input')[0]; 270 this.decode = function(parent,xml) {
271 specificationNode.randomiseOrder = input.checked; 271 this.location = xml.getAttribute('location');
272 while(opt.nextSibling != null) 272 if (this.location == 'before'){this.location = 'pre';}
273 { 273 else if (this.location == 'after'){this.location = 'post';}
274 opt = opt.nextSibling; 274 for (var i in xml.children)
275 input = opt.getElementsByTagName('input')[0]; 275 {
276 if (input.checked) 276 if(isNaN(Number(i))==true){break;}
277 { 277 var node = new this.OptionNode();
278 specificationNode.commonInterface.options.push(new specificationNode.commonInterface.optionNode(input)); 278 node.decode(parent,xml.children[i]);
279 } 279 this.options.push(node);
280 280 }
281 } 281 };
282 popupInstance.advanceState(); 282 this.encode = function(root) {
283 }; 283 var node = root.createElement('survey');
284 this.popupFooter.appendChild(button); 284 node.setAttribute('location',this.location);
285 break; 285 for (var i=0; i<this.options.length; i++)
286 case 3: 286 {
287 audioObjects = []; 287 node.appendChild(this.options[i].exportXML());
288 this.popupTitleText.textContent = "Test Page"; 288 }
289 var span = document.createElement('span'); 289 return node;
290 span.textContent = "Drag and drop your audio files into the box below to add them to a test page"; 290 };
291 this.popupBody.appendChild(span); 291 };
292 var dnd = document.createElement('div'); 292
293 dnd.id = "audio-holder-drop"; 293 this.interfaceNode = function()
294 dnd.style.width = "100%"; 294 {
295 dnd.style.minHeight = "50px"; 295 this.title = null;
296 dnd.style.maxHeight = "220px"; 296 this.name = null;
297 dnd.style.overflow = 'auto'; 297 this.options = [];
298 dnd.className = "dragndrop"; 298 this.scales = [];
299 dnd.ondragover = function(e) { 299 this.schema = specification.schema.getAllElementsByName('interface')[1];
300 if(e.preventDefault) {e.preventDefault();} 300
301 return false; 301 this.decode = function(parent,xml) {
302 }; 302 this.name = xml.getAttribute('name');
303 dnd.ondragenter = function(e) { 303 var titleNode = xml.getElementsByTagName('title');
304 if(e.preventDefault) {e.preventDefault();} 304 if (titleNode.length == 1)
305 return false; 305 {
306 }; 306 this.title = titleNode[0].textContent;
307 dnd.ondrop = function(e) { 307 }
308 if(e.preventDefault) {e.preventDefault();} 308 var interfaceOptionNodes = xml.getElementsByTagName('interfaceoption');
309 var dt = e.dataTransfer; 309 // Extract interfaceoption node schema
310 var body = document.getElementById("audio-holder-drop"); 310 var interfaceOptionNodeSchema = this.schema.getAllElementsByName('interfaceoption')[0];
311 var files = dt.files; 311 var attributeMap = interfaceOptionNodeSchema.getAllElementsByTagName('xs:attribute');
312 for (var i = 0, f; f = files[i]; i++) 312 for (var i=0; i<interfaceOptionNodes.length; i++)
313 { 313 {
314 var ao = new audioObject(); 314 var ioNode = interfaceOptionNodes[i];
315 ao.constructTrack(f); 315 var option = {};
316 audioObjects.push(ao); 316 for (var j=0; j<attributeMap.length; j++)
317 var dndHeader = document.createElement('div'); 317 {
318 dndHeader.style.width = "100%"; 318 var attributeName = attributeMap[j].getAttribute('name') || attributeMap[j].getAttribute('ref');
319 dndHeader.style.height = "20px"; 319 var projectAttr = ioNode.getAttribute(attributeName);
320 dndHeader.style.borderBottom = "#DDD"; 320 projectAttr = parent.processAttribute(projectAttr,attributeMap[j]);
321 dndHeader.style.borderBottomWidth = "1px"; 321 switch(typeof projectAttr)
322 dndHeader.style.borderBottomStyle = "solid"; 322 {
323 dndHeader.setAttribute('aoID',audioObjects.length-1); 323 case "number":
324 var dndHInclude = document.createElement('div'); 324 case "boolean":
325 dndHInclude.style.width = "30px"; 325 eval('option.'+attributeName+' = '+projectAttr);
326 dndHInclude.className = "dndheaderelement"; 326 break;
327 var includeCheck = document.createElement('input'); 327 case "string":
328 includeCheck.type = "checkbox"; 328 eval('option.'+attributeName+' = "'+projectAttr+'"');
329 includeCheck.name = "include-check"; 329 break;
330 includeCheck.checked = true; 330 }
331 includeCheck.onchange = function() 331 }
332 { 332 this.options.push(option);
333 var i = event.currentTarget.parentElement.parentElement.getAttribute('aoID'); 333 }
334 audioObjects[i].include = event.currentTarget.checked; 334
335 }; 335 // Now the scales nodes
336 dndHInclude.appendChild(includeCheck); 336 var scaleParent = xml.getElementsByTagName('scales');
337 dndHeader.appendChild(dndHInclude); 337 if (scaleParent.length == 1) {
338 var dndHTitle = document.createElement('div'); 338 scaleParent = scaleParent[0];
339 dndHTitle.style.width = "180px"; 339 for (var i=0; i<scaleParent.children.length; i++) {
340 dndHTitle.className = "dndheaderelement"; 340 var child = scaleParent.children[i];
341 var text = document.createElement('span'); 341 this.scales.push({
342 text.textContent = f.name; 342 text: child.textContent,
343 dndHTitle.appendChild(text); 343 position: Number(child.getAttribute('position'))
344 dndHeader.appendChild(dndHTitle); 344 });
345 var dndHID = document.createElement('div'); 345 }
346 dndHID.style.width = "100px"; 346 }
347 dndHID.className = "dndheaderelement"; 347 };
348 var IDInput = document.createElement('input'); 348
349 IDInput.name = "audio-fragment-ID"; 349 this.encode = function(root) {
350 IDInput.value = f.name.split('.')[0]; 350
351 IDInput.onchange = function() 351 };
352 { 352 };
353 var allIDInput = document.getElementsByName("audio-fragment-ID"); 353
354 var isCopy = new Array(allIDInput.length); 354 this.metricNode = function() {
355 isCopy.fill(0,0,this.length); 355 this.enabled = [];
356 if (allIDInput.length > 1) 356 this.decode = function(parent, xml) {
357 { 357 var children = xml.getElementsByTagName('metricenable');
358 for (var j=0; j<allIDInput.length; j++) 358 for (var i in children) {
359 { 359 if (isNaN(Number(i)) == true){break;}
360 var textCompare1 = allIDInput[j].value; 360 this.enabled.push(children[i].textContent);
361 for (var k=j+1; k<allIDInput.length; k++) 361 }
362 { 362 }
363 var textCompare2 = allIDInput[k].value; 363 this.encode = function(root) {
364 if (textCompare1 == textCompare2) 364 var node = root.createElement('metric');
365 { 365 for (var i in this.enabled)
366 isCopy[j] = 1; 366 {
367 isCopy[k] = 1; 367 if (isNaN(Number(i)) == true){break;}
368 } 368 var child = root.createElement('metricenable');
369 } 369 child.textContent = this.enabled[i];
370 } 370 node.appendChild(child);
371 } 371 }
372 var button = document.getElementById('submit'); 372 return node;
373 button.disabled = false; 373 }
374 for (var j=0; j<allIDInput.length; j++) 374 }
375 { 375
376 if (isCopy[j] == 1) 376 this.page = function() {
377 { 377 this.presentedId = undefined;
378 allIDInput[j].style.backgroundColor = '#F22'; 378 this.id = undefined;
379 button.disabled = true; 379 this.hostURL = undefined;
380 } 380 this.randomiseOrder = undefined;
381 else 381 this.loop = undefined;
382 { 382 this.showElementComments = undefined;
383 allIDInput[j].style.backgroundColor = '#FFF'; 383 this.outsideReference = null;
384 audioObjects[j].id = allIDInput[j].value; 384 this.loudness = null;
385 } 385 this.preTest = null;
386 } 386 this.postTest = null;
387 }; 387 this.interfaces = [];
388 IDInput.style.width = "96px"; 388 this.commentBoxPrefix = "Comment on track";
389 dndHID.appendChild(IDInput); 389 this.audioElements = [];
390 dndHeader.appendChild(dndHID); 390 this.commentQuestions = [];
391 var dndHPlay = document.createElement('div'); 391 this.schema = specification.schema.getAllElementsByName("page")[0];
392 dndHPlay.style.width = "100px"; 392
393 dndHPlay.className = "dndheaderelement"; 393 this.decode = function(parent,xml)
394 var audio = document.createElement('button'); 394 {
395 audio.textContent = 'Play'; 395 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
396 audio.className = "popupButton"; 396 for (var i=0; i<attributeMap.length; i++)
397 audio.style.height = "inherit"; 397 {
398 audio.onclick = function() 398 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
399 { 399 var projectAttr = xml.getAttribute(attributeName);
400 var i = event.currentTarget.parentElement.parentElement.getAttribute('aoID'); 400 projectAttr = parent.processAttribute(projectAttr,attributeMap[i]);
401 audioObjects[i].play(); 401 switch(typeof projectAttr)
402 }; 402 {
403 dndHPlay.appendChild(audio); 403 case "number":
404 dndHeader.appendChild(dndHPlay); 404 case "boolean":
405 dnd.appendChild(dndHeader); 405 eval('this.'+attributeName+' = '+projectAttr);
406 IDInput.onchange(); 406 break;
407 } 407 case "string":
408 }; 408 eval('this.'+attributeName+' = "'+projectAttr+'"');
409 var dndHeader = document.createElement('div'); 409 break;
410 dndHeader.style.width = "100%"; 410 }
411 dndHeader.style.height = "15px"; 411 }
412 dndHeader.style.borderBottom = "#DDD"; 412
413 dndHeader.style.borderBottomWidth = "1px"; 413 // Get the Comment Box Prefix
414 dndHeader.style.borderBottomStyle = "solid"; 414 var CBP = xml.getElementsByTagName('commentboxprefix');
415 var dndHInclude = document.createElement('div'); 415 if (CBP.length != 0) {
416 dndHInclude.style.width = "30px"; 416 this.commentBoxPrefix = CBP[0].textContent;
417 dndHInclude.className = "dndheaderelement"; 417 }
418 var text = document.createElement('span'); 418
419 text.textContent = "Inc."; 419 // Now decode the interfaces
420 dndHInclude.appendChild(text); 420 var interfaceNode = xml.getElementsByTagName('interface');
421 dndHeader.appendChild(dndHInclude); 421 for (var i=0; i<interfaceNode.length; i++)
422 var dndHTitle = document.createElement('div'); 422 {
423 dndHTitle.style.width = "180px"; 423 var node = new parent.interfaceNode();
424 dndHTitle.className = "dndheaderelement"; 424 node.decode(this,interfaceNode[i],parent.schema.getAllElementsByName('interface')[1]);
425 text = document.createElement('span'); 425 this.interfaces.push(node);
426 text.textContent = "File Name"; 426 }
427 dndHTitle.appendChild(text); 427
428 dndHeader.appendChild(dndHTitle); 428 // Now process the survey node options
429 var dndHID = document.createElement('div'); 429 var survey = xml.getElementsByTagName('survey');
430 dndHID.style.width = "100px"; 430 var surveySchema = parent.schema.getAllElementsByName('survey')[0];
431 dndHID.className = "dndheaderelement"; 431 for (var i in survey) {
432 text = document.createElement('span'); 432 if (isNaN(Number(i)) == true){break;}
433 text.textContent = "ID"; 433 var location = survey[i].getAttribute('location');
434 dndHID.appendChild(text); 434 if (location == 'pre' || location == 'before')
435 dndHeader.appendChild(dndHID); 435 {
436 var dndHPlay = document.createElement('div'); 436 if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");}
437 dndHPlay.style.width = "100px"; 437 else {
438 dndHPlay.className = "dndheaderelement"; 438 this.preTest = new parent.surveyNode();
439 text = document.createElement('span'); 439 this.preTest.decode(parent,survey[i],surveySchema);
440 text.textContent = "Sample"; 440 }
441 dndHPlay.appendChild(text); 441 } else if (location == 'post' || location == 'after') {
442 dndHeader.appendChild(dndHPlay); 442 if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");}
443 dnd.appendChild(dndHeader); 443 else {
444 this.popupBody.appendChild(dnd); 444 this.postTest = new parent.surveyNode();
445 var button = document.createElement('button'); 445 this.postTest.decode(parent,survey[i],surveySchema);
446 button.id = 'submit'; 446 }
447 button.className = "popupButton"; 447 }
448 button.textContent = "Submit"; 448 }
449 button.onclick = function(event) 449
450 { 450 // Now process the audioelement tags
451 // Construct the audio-holder nodes; 451 var audioElements = xml.getElementsByTagName('audioelement');
452 for (var i=0; i<audioObjects.length; i++) 452 for (var i=0; i<audioElements.length; i++)
453 { 453 {
454 if (!audioObjects[i].include) 454 var node = new this.audioElementNode();
455 { 455 node.decode(this,audioElements[i]);
456 audioObjects.pop(audioObjects[i]); 456 this.audioElements.push(node);
457 } 457 }
458 } 458
459 if (audioObjects.length != 0) 459 // Now decode the commentquestions
460 { 460 var commentQuestions = xml.getElementsByTagName('commentquestion');
461 popupInstance.advanceState(); 461 for (var i=0; i<commentQuestions.length; i++)
462 } 462 {
463 }; 463 var node = new this.commentQuestionNode();
464 this.popupFooter.appendChild(button); 464 node.decode(parent,commentQuestions[i]);
465 break; 465 this.commentQuestions.push(node);
466 case 4: 466 }
467 this.popupTitleText.textContent = "Test Page - Options"; 467 };
468 var span = document.createElement('span'); 468
469 span.textContent = "Set your test page options here"; 469 this.encode = function(root)
470 this.popupBody.appendChild(span); 470 {
471 var pair = document.createElement('div'); 471 var AHNode = root.createElement("audioHolder");
472 pair.style.margin = '5px'; 472 AHNode.id = this.id;
473 var text = document.createElement('span'); 473 AHNode.setAttribute("hostURL",this.hostURL);
474 text.textContent = "Page ID:"; 474 AHNode.setAttribute("sampleRate",this.sampleRate);
475 var input = document.createElement('input'); 475 AHNode.setAttribute("randomiseOrder",this.randomiseOrder);
476 input.value = specificationNode.audioHolders.length; 476 AHNode.setAttribute("repeatCount",this.repeatCount);
477 input.id = "id"; 477 AHNode.setAttribute("loop",this.loop);
478 pair.appendChild(text); 478 AHNode.setAttribute("elementComments",this.elementComments);
479 pair.appendChild(input); 479 if(this.loudness != null) {AHNode.setAttribute("loudness",this.loudness);}
480 this.popupBody.appendChild(pair); 480 if(this.initialPosition != null) {
481 pair = document.createElement('div'); 481 AHNode.setAttribute("loudness",this.initialPosition*100);
482 pair.style.margin = '5px'; 482 }
483 text = document.createElement('span'); 483 for (var i=0; i<this.interfaces.length; i++)
484 text.textContent = "Randomise Fragment Order"; 484 {
485 input = document.createElement('input'); 485 AHNode.appendChild(this.interfaces[i].encode(root));
486 input.type = "checkbox"; 486 }
487 input.id = "randomiseOrder"; 487
488 pair.appendChild(input); 488 for (var i=0; i<this.audioElements.length; i++) {
489 pair.appendChild(text); 489 AHNode.appendChild(this.audioElements[i].encode(root));
490 this.popupBody.appendChild(pair); 490 }
491 pair = document.createElement('div'); 491 // Create <CommentQuestion>
492 pair.style.margin = '5px'; 492 for (var i=0; i<this.commentQuestions.length; i++)
493 text = document.createElement('span'); 493 {
494 text.textContent = "Loop Fragment Playback"; 494 AHNode.appendChild(this.commentQuestions[i].exportXML(root));
495 input = document.createElement('input'); 495 }
496 input.type = "checkbox"; 496
497 input.id = "loop"; 497 // Create <PreTest>
498 pair.appendChild(input); 498 var AHPreTest = root.createElement("PreTest");
499 pair.appendChild(text); 499 for (var i=0; i<this.preTest.options.length; i++)
500 this.popupBody.appendChild(pair); 500 {
501 pair = document.createElement('div'); 501 AHPreTest.appendChild(this.preTest.options[i].exportXML(root));
502 pair.style.margin = '5px'; 502 }
503 text = document.createElement('span'); 503
504 text.textContent = "Show fragment comment boxes"; 504 var AHPostTest = root.createElement("PostTest");
505 input = document.createElement('input'); 505 for (var i=0; i<this.postTest.options.length; i++)
506 input.type = "checkbox"; 506 {
507 input.id = "elementComments"; 507 AHPostTest.appendChild(this.postTest.options[i].exportXML(root));
508 pair.appendChild(input); 508 }
509 pair.appendChild(text); 509 AHNode.appendChild(AHPreTest);
510 this.popupBody.appendChild(pair); 510 AHNode.appendChild(AHPostTest);
511 var button = document.createElement('button'); 511 return AHNode;
512 button.id = 'submit'; 512 };
513 button.className = "popupButton"; 513
514 button.textContent = "Next"; 514 this.commentQuestionNode = function() {
515 button.onclick = function(event) 515 this.id = null;
516 { 516 this.type = undefined;
517 var ah = new specificationNode.audioHolderNode(specificationNode); 517 this.options = [];
518 ah.id = document.getElementById('id').value; 518 this.statement = undefined;
519 ah.presentedId = specificationNode.audioHolders.length; 519 this.schema = specification.schema.getAllElementsByName('commentquestion')[0];
520 ah.hostURL = ah.id+'/'; 520 this.decode = function(parent,xml)
521 ah.randomiseOrder = document.getElementById('randomiseOrder').checked; 521 {
522 ah.loop = document.getElementById('loop').checked; 522 this.id = xml.id;
523 ah.elementComments = document.getElementById('elementComments').checked; 523 this.type = xml.getAttribute('type');
524 for (var i=0; i<audioObjects.length; i++) 524 this.statement = xml.getElementsByTagName('statement')[0].textContent;
525 { 525 var optNodes = xml.getElementsByTagName('option');
526 ah.audioElements.push(new ah.audioElementNode(ah,audioObjects[i])); 526 for (var i=0; i<optNodes.length; i++)
527 } 527 {
528 specificationNode.audioHolders.push(ah); 528 var optNode = optNodes[i];
529 popupInstance.advanceState(); 529 this.options.push({
530 }; 530 name: optNode.getAttribute('name'),
531 this.popupFooter.appendChild(button); 531 text: optNode.textContent
532 break; 532 });
533 case 5: 533 }
534 this.dataTransfer = null; 534 };
535 this.popupTitleText.textContent = "Test Page - Pre/Post Survey"; 535
536 var span = document.createElement('span'); 536 this.encode = function(root)
537 span.textContent = "Add your pre test page options here"; 537 {
538 this.popupBody.appendChild(span); 538
539 var preHolder = document.createElement('div'); 539 };
540 preHolder.id = "preHolder"; 540 };
541 preHolder.style.width = "460px"; 541
542 preHolder.style.minHeight = "100px"; 542 this.audioElementNode = function() {
543 preHolder.style.maxHeight = "220px"; 543 this.url = null;
544 preHolder.style.overflow = 'auto'; 544 this.id = null;
545 preHolder.style.border = "black"; 545 this.parent = null;
546 preHolder.style.borderStyle = "solid"; 546 this.type = null;
547 preHolder.style.borderWidth = "1px"; 547 this.marker = false;
548 this.popupBody.appendChild(preHolder); 548 this.enforce = false;
549 var audioHolder = specificationNode.audioHolders[specificationNode.audioHolders.length-1]; 549 this.gain = 1.0;
550 var preHeaderHolder = document.createElement('div'); 550 this.schema = specification.schema.getAllElementsByName('audioelement')[0];;
551 preHeaderHolder.style.width = "456px"; 551 this.parent = null;
552 preHeaderHolder.style.height= "20px"; 552 this.decode = function(parent,xml)
553 preHeaderHolder.style.margin= "2px"; 553 {
554 preHeaderHolder.style.borderBottom = "#DDD"; 554 this.parent = parent;
555 preHeaderHolder.style.borderBottomWidth = "1px"; 555 var attributeMap = this.schema.getAllElementsByTagName('xs:attribute');
556 preHeaderHolder.style.borderBottomStyle = "solid"; 556 for (var i=0; i<attributeMap.length; i++)
557 var mvH = document.createElement('div'); 557 {
558 mvH.className = "dndheaderelement"; 558 var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref');
559 mvH.style.width = "50px"; 559 var projectAttr = xml.getAttribute(attributeName);
560 var text = document.createElement('span'); 560 projectAttr = specification.processAttribute(projectAttr,attributeMap[i]);
561 text.textContent = "Order"; 561 switch(typeof projectAttr)
562 mvH.appendChild(text); 562 {
563 preHeaderHolder.appendChild(mvH); 563 case "number":
564 var idH = document.createElement('div'); 564 case "boolean":
565 idH.className = "dndheaderelement"; 565 eval('this.'+attributeName+' = '+projectAttr);
566 idH.style.width = "150px"; 566 break;
567 text = document.createElement('span'); 567 case "string":
568 text.textContent = "ID"; 568 eval('this.'+attributeName+' = "'+projectAttr+'"');
569 idH.appendChild(text); 569 break;
570 preHeaderHolder.appendChild(idH); 570 }
571 var tH = document.createElement('div'); 571 }
572 tH.className = "dndheaderelement"; 572
573 tH.style.width = "150px"; 573 };
574 text = document.createElement('span'); 574 this.encode = function(root)
575 text.textContent = "Type"; 575 {
576 tH.appendChild(text); 576 var AENode = root.createElement("audioElements");
577 preHeaderHolder.appendChild(tH); 577 AENode.id = this.id;
578 var editH = document.createElement('div'); 578 AENode.setAttribute("url",this.url);
579 editH.className = "dndheaderelement"; 579 AENode.setAttribute("type",this.type);
580 editH.style.width = "50px"; 580 AENode.setAttribute("gain",linearToDecibel(this.gain));
581 text = document.createElement('span'); 581 if (this.marker != false)
582 text.textContent = "Edit"; 582 {
583 editH.appendChild(text); 583 AENode.setAttribute("marker",this.marker*100);
584 preHeaderHolder.appendChild(editH); 584 }
585 var deleteH = document.createElement('div'); 585 return AENode;
586 deleteH.className = "dndheaderelement"; 586 };
587 deleteH.style.width = "50px"; 587 };
588 text = document.createElement('span'); 588 };
589 text.textContent = "Delete"; 589 }
590 deleteH.appendChild(text); 590 </script>
591 preHeaderHolder.appendChild(deleteH); 591 <script type="text/javascript" src="test_core.js"/>
592 preHolder.appendChild(preHeaderHolder); 592 <script type="text/javascript">
593 593
594 594 </script>
595 for (var i=0; i<audioHolder.preTest.options.length; i++) 595 </head>
596 { 596 <body>
597 var optionNode = audioHolder.preTest.options[i]; 597 <div id="popupHolder"></div>
598 var entry = document.createElement('div'); 598 <div id="blanket"></div>
599 entry.style.width = "456px"; 599 <div id="content"></div>
600 entry.style.height= "20px"; 600 </body>
601 entry.style.margin= "2px";
602 entry.style.borderBottom = "#DDD";
603 entry.style.borderBottomWidth = "1px";
604 entry.style.borderBottomStyle = "solid";
605 entry.setAttribute("node-id",i);
606 var node = audioHolder.preTest.options[i];
607 var mvH = document.createElement('div');
608 mvH.className = "dndheaderelement";
609 mvH.style.width = "50px";
610 var mvup = document.createElement("button");
611 mvup.textContent = "Up";
612 mvup.style.width = "25px";
613 mvup.style.padding = "1px 0px";
614 mvup.onclick = function()
615 {
616 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
617 if (i != 0)
618 {
619 var next = audioHolder.preTest.options[i-1];
620 var cur = audioHolder.preTest.options[i];
621 audioHolder.preTest.options[i-1] = cur;
622 audioHolder.preTest.options[i] = next;
623 popupInstance.state = 5;
624 popupInstance.advanceState();
625 }
626 };
627 mvH.appendChild(mvup);
628 var mvdn = document.createElement("button");
629 mvdn.textContent = "Dn";
630 mvdn.style.width = "25px";
631 mvdn.style.padding = "1px 0px";
632 mvdn.onclick = function()
633 {
634 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
635 if (i != audioHolder.preTest.options.length-1)
636 {
637 var next = audioHolder.preTest.options[i+1];
638 var cur = audioHolder.preTest.options[i];
639 audioHolder.preTest.options[i+1] = cur;
640 audioHolder.preTest.options[i] = next;
641 popupInstance.state = 5;
642 popupInstance.advanceState();
643 }
644 };
645 mvH.appendChild(mvdn);
646 entry.appendChild(mvH);
647 var idH = document.createElement('div');
648 idH.className = "dndheaderelement";
649 idH.style.width = "150px";
650 if (optionNode.type != "statement")
651 {
652 var span = document.createElement('span');
653 span.textContent = optionNode.id;
654 idH.appendChild(span);
655 }
656 entry.appendChild(idH);
657 var typeH = document.createElement('div');
658 typeH.className = "dndheaderelement";
659 typeH.style.width = "150px";
660 var span = document.createElement('span');
661 span.textContent = optionNode.type;
662 typeH.appendChild(span);
663 entry.appendChild(typeH);
664 var editH = document.createElement('div');
665 editH.className = "dndheaderelement";
666 editH.style.width = "50px";
667 var editButton = document.createElement("button");
668 editButton.textContent = "Edit";
669 editButton.style.width = "48px";
670 editButton.style.padding = "1px 0px";
671 editButton.onclick = function()
672 {
673 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
674 popupInstance.dataTransfer = new function() {
675 this.title = "Edit Test Node";
676 this.parent = specificationNode.audioHolders[specificationNode.audioHolders.length-1].preTest;
677 this.node = this.parent.options[i];
678 this.previousState = 5;
679 };
680 popupInstance.advanceState();
681 };
682 editH.appendChild(editButton);
683 entry.appendChild(editH);
684 var deleteH = document.createElement('div');
685 deleteH.className = "dndheaderelement";
686 deleteH.style.width = "50px";
687 var deleteButton = document.createElement("button");
688 deleteButton.textContent = "Del";
689 deleteButton.style.width = "48px";
690 deleteButton.style.padding = "1px 0px";
691 deleteButton.onclick = function()
692 {
693 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
694 var j = i+1;
695 while(j < audioHolder.preTest.options.length)
696 {
697 audioHolder.preTest.options[i] = audioHolder.preTest.options[j];
698 j++;
699 i++;
700 }
701 audioHolder.preTest.options.pop();
702 popupInstance.state = 5;
703 popupInstance.advanceState();
704 };
705 deleteH.appendChild(deleteButton);
706 entry.appendChild(deleteH);
707 preHolder.appendChild(entry);
708 }
709 var entry = document.createElement('div');
710 entry.style.width = "456px";
711 entry.style.height= "20px";
712 entry.style.margin= "2px";
713 entry.style.borderBottom = "#DDD";
714 entry.style.borderBottomWidth = "1px";
715 entry.style.borderBottomStyle = "solid";
716 entry.align = "center";
717 var addPre = document.createElement('button');
718 addPre.className = "popupButton";
719 addPre.textContent = "Add New Entry";
720 addPre.style.height = "20px";
721 addPre.onclick = function()
722 {
723 popupInstance.dataTransfer = new function() {
724 this.title = "New Pre Test Node";
725 this.parent = specificationNode.audioHolders[specificationNode.audioHolders.length-1].preTest;
726 this.node = null;
727 this.previousState = 5;
728 };
729 popupInstance.advanceState();
730 };
731 entry.appendChild(addPre);
732 preHolder.appendChild(entry);
733
734 var span = document.createElement('span');
735 span.textContent = "Add your post test page options here";
736 this.popupBody.appendChild(span);
737 var postHolder = document.createElement('div');
738 postHolder.id = "preHolder";
739 postHolder.style.width = "100%";
740 postHolder.style.minHeight = "100px";
741 postHolder.style.maxHeight = "220px";
742 postHolder.style.overflow = 'auto';
743 postHolder.style.border = "black";
744 postHolder.style.borderStyle = "solid";
745 postHolder.style.borderWidth = "1px";
746 this.popupBody.appendChild(postHolder);
747 var postHeaderHolder = document.createElement('div');
748 postHeaderHolder.style.width = "456px";
749 postHeaderHolder.style.height= "20px";
750 postHeaderHolder.style.margin= "2px";
751 postHeaderHolder.style.borderBottom = "#DDD";
752 postHeaderHolder.style.borderBottomWidth = "1px";
753 postHeaderHolder.style.borderBottomStyle = "solid";
754 var mvH = document.createElement('div');
755 mvH.className = "dndheaderelement";
756 mvH.style.width = "50px";
757 var text = document.createElement('span');
758 text.textContent = "Order";
759 mvH.appendChild(text);
760 postHeaderHolder.appendChild(mvH);
761 var idH = document.createElement('div');
762 idH.className = "dndheaderelement";
763 idH.style.width = "150px";
764 text = document.createElement('span');
765 text.textContent = "ID";
766 idH.appendChild(text);
767 postHeaderHolder.appendChild(idH);
768 var tH = document.createElement('div');
769 tH.className = "dndheaderelement";
770 tH.style.width = "150px";
771 text = document.createElement('span');
772 text.textContent = "Type";
773 tH.appendChild(text);
774 postHeaderHolder.appendChild(tH);
775 var editH = document.createElement('div');
776 editH.className = "dndheaderelement";
777 editH.style.width = "50px";
778 text = document.createElement('span');
779 text.textContent = "Edit";
780 editH.appendChild(text);
781 postHeaderHolder.appendChild(editH);
782 var deleteH = document.createElement('div');
783 deleteH.className = "dndheaderelement";
784 deleteH.style.width = "50px";
785 text = document.createElement('span');
786 text.textContent = "Delete";
787 deleteH.appendChild(text);
788 postHeaderHolder.appendChild(deleteH);
789 postHolder.appendChild(postHeaderHolder);
790
791 for (var i=0; i<audioHolder.postTest.options.length; i++)
792 {
793 var optionNode = audioHolder.postTest.options[i];
794 var entry = document.createElement('div');
795 entry.style.width = "456px";
796 entry.style.height= "20px";
797 entry.style.margin= "2px";
798 entry.style.borderBottom = "#DDD";
799 entry.style.borderBottomWidth = "1px";
800 entry.style.borderBottomStyle = "solid";
801 entry.setAttribute("node-id",i);
802 var node = audioHolder.postTest.options[i];
803 var mvH = document.createElement('div');
804 mvH.className = "dndheaderelement";
805 mvH.style.width = "50px";
806 var mvup = document.createElement("button");
807 mvup.textContent = "Up";
808 mvup.style.width = "25px";
809 mvup.style.padding = "1px 0px";
810 mvup.onclick = function()
811 {
812 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
813 if (i != 0)
814 {
815 var next = audioHolder.postTest.options[i-1];
816 var cur = audioHolder.postTest.options[i];
817 audioHolder.postTest.options[i-1] = cur;
818 audioHolder.postTest.options[i] = next;
819 popupInstance.state = 5;
820 popupInstance.advanceState();
821 }
822 };
823 mvH.appendChild(mvup);
824 var mvdn = document.createElement("button");
825 mvdn.textContent = "Dn";
826 mvdn.style.width = "25px";
827 mvdn.style.padding = "1px 0px";
828 mvdn.onclick = function()
829 {
830 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
831 if (i != audioHolder.postTest.options.length-1)
832 {
833 var next = audioHolder.postTest.options[i+1];
834 var cur = audioHolder.postTest.options[i];
835 audioHolder.postTest.options[i+1] = cur;
836 audioHolder.postTest.options[i] = next;
837 popupInstance.state = 5;
838 popupInstance.advanceState();
839 }
840 };
841 mvH.appendChild(mvdn);
842 entry.appendChild(mvH);
843 var idH = document.createElement('div');
844 idH.className = "dndheaderelement";
845 idH.style.width = "150px";
846 if (optionNode.type != "statement")
847 {
848 var span = document.createElement('span');
849 span.textContent = optionNode.id;
850 idH.appendChild(span);
851 }
852 entry.appendChild(idH);
853 var typeH = document.createElement('div');
854 typeH.className = "dndheaderelement";
855 typeH.style.width = "150px";
856 var span = document.createElement('span');
857 span.textContent = optionNode.type;
858 typeH.appendChild(span);
859 entry.appendChild(typeH);
860 var editH = document.createElement('div');
861 editH.className = "dndheaderelement";
862 editH.style.width = "50px";
863 var editButton = document.createElement("button");
864 editButton.textContent = "Edit";
865 editButton.style.width = "48px";
866 editButton.style.padding = "1px 0px";
867 editButton.onclick = function()
868 {
869 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
870 popupInstance.dataTransfer = new function() {
871 this.title = "Edit Test Node";
872 this.parent = specificationNode.audioHolders[specificationNode.audioHolders.length-1].postTest;
873 this.node = this.parent.options[i];
874 this.previousState = 5;
875 };
876 popupInstance.advanceState();
877 };
878 editH.appendChild(editButton);
879 entry.appendChild(editH);
880 var deleteH = document.createElement('div');
881 deleteH.className = "dndheaderelement";
882 deleteH.style.width = "50px";
883 var deleteButton = document.createElement("button");
884 deleteButton.textContent = "Del";
885 deleteButton.style.width = "48px";
886 deleteButton.style.padding = "1px 0px";
887 deleteButton.onclick = function()
888 {
889 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
890 var j = i+1;
891 while(j < audioHolder.postTest.options.length)
892 {
893 audioHolder.postTest.options[i] = audioHolder.postTest.options[j];
894 j++;
895 i++;
896 }
897 audioHolder.postTest.options.pop();
898 popupInstance.state = 5;
899 popupInstance.advanceState();
900 };
901 deleteH.appendChild(deleteButton);
902 entry.appendChild(deleteH);
903 postHolder.appendChild(entry);
904 }
905
906 var entry = document.createElement('div');
907 entry.style.width = "456px";
908 entry.style.height= "20px";
909 entry.style.margin= "2px";
910 entry.style.borderBottom = "#DDD";
911 entry.style.borderBottomWidth = "1px";
912 entry.style.borderBottomStyle = "solid";
913 entry.align = "center";
914 var addPost = document.createElement('button');
915 addPost.className = "popupButton";
916 addPost.textContent = "Add New Entry";
917 addPost.style.height = "20px";
918 addPost.onclick = function()
919 {
920 popupInstance.dataTransfer = new function() {
921 this.title = "New Pre Test Node";
922 this.parent = specificationNode.audioHolders[specificationNode.audioHolders.length-1].postTest;
923 this.node = null;
924 this.previousState = 5;
925 };
926 popupInstance.advanceState();
927 };
928 entry.appendChild(addPost);
929 postHolder.appendChild(entry);
930
931 var button = document.createElement('button');
932 button.id = 'submit';
933 button.className = "popupButton";
934 button.textContent = "Finish";
935 button.onclick = function(event)
936 {
937 popupInstance.state = 7;
938 popupInstance.advanceState();
939 };
940 this.popupFooter.appendChild(button);
941 button = document.createElement('button');
942 button.id = 'submit';
943 button.className = "popupButton";
944 button.textContent = "Add Another Page";
945 button.onclick = function(event)
946 {
947 popupInstance.state = 3;
948 popupInstance.advanceState();
949 };
950 this.popupFooter.appendChild(button);
951 break;
952 case 6:
953 this.popupTitleText.textContent = this.dataTransfer.title;
954 var span = document.createElement('span');
955 span.textContent = "Select survey settings here";
956 this.popupBody.appendChild(span);
957 var div = document.createElement('div');
958 span = document.createElement("span");
959 span.textContent = "Survey Type";
960 var select = document.createElement("select");
961 select.id="survey-select";
962 var option = document.createElement('option');
963 option.textContent = "Statement";
964 option.value = "statement";
965 select.appendChild(option);
966 option = document.createElement('option');
967 option.textContent = "Question";
968 option.value = "question";
969 select.appendChild(option);
970 option = document.createElement('option');
971 option.textContent = "Number";
972 option.value = "number";
973 select.appendChild(option);
974 option = document.createElement('option');
975 option.textContent = "Radio";
976 option.value = "radio";
977 select.appendChild(option);
978 option = document.createElement('option');
979 option.textContent = "Checkbox";
980 option.value = "checkbox";
981 select.appendChild(option);
982 this.popupBody.appendChild(select);
983 var options = document.createElement('div');
984 options.id = "survey-options";
985 this.popupBody.appendChild(options);
986 var button = document.createElement('button');
987 button.id = 'submit';
988 button.className = "popupButton";
989 button.textContent = "Add";
990 button.onclick = function(event)
991 {
992 var parent = popupInstance.dataTransfer.parent;
993 if (popupInstance.dataTransfer.node == null)
994 {
995 var node = new parent.OptionNode();
996 } else
997 {
998 var node = popupInstance.dataTransfer.node;
999 }
1000 node.type = document.getElementById("survey-select").value;
1001 switch(node.type)
1002 {
1003 case "statement":
1004 node.statement = document.getElementById("statement").value;
1005 break;
1006 case "question":
1007 node.question = document.getElementById("question").value;
1008 node.id = document.getElementById("ID").value;
1009 node.mandatory = document.getElementById("mandatory").checked;
1010 node.boxsize = document.getElementById("boxsize").value;
1011 break;
1012 }
1013 if (popupInstance.dataTransfer.node == null)
1014 {parent.options.push(node);}
1015 popupInstance.state = popupInstance.dataTransfer.previousState;
1016 popupInstance.advanceState();
1017 };
1018 this.popupFooter.appendChild(button);
1019 select.onchange = function()
1020 {
1021 var options = document.getElementById("survey-options");
1022 options.innerHTML = null;
1023 switch(this.value)
1024 {
1025 case "statement":
1026 var span = document.createElement('span');
1027 span.textContent = "Enter Statement";
1028 var tA = document.createElement('textarea');
1029 tA.id = "statement";
1030 tA.style.width = "460px";
1031 tA.style.height = "96px";
1032 if (popupInstance.dataTransfer.node != null)
1033 {tA.value = this.dataTransfer.node.statement;}
1034 options.appendChild(span);
1035 options.appendChild(tA);
1036 break;
1037 case "question":
1038 var span = document.createElement('span');
1039 span.textContent = "Enter Question";
1040 var tA = document.createElement('textarea');
1041 tA.style.width = "460px";
1042 tA.style.height = "54px";
1043 tA.id = "question";
1044 options.appendChild(span);
1045 options.appendChild(tA);
1046 var div = document.createElement('div');
1047 var input = document.createElement('input');
1048 input.id = "ID";
1049 span = document.createElement('span');
1050 span.textContent = "ID:";
1051 div.appendChild(span);
1052 div.appendChild(input);
1053 options.appendChild(div);
1054 div = document.createElement('div');
1055 input = document.createElement('input');
1056 input.type = "checkbox";
1057 input.id = "mandatory";
1058 span = document.createElement('span');
1059 span.textContent = "Mandatory";
1060 div.appendChild(span);
1061 div.appendChild(input);
1062 options.appendChild(div);
1063 div = document.createElement('div');
1064 var boxsize = document.createElement("select");
1065 boxsize.id = "boxsize";
1066 var selOpt = document.createElement("option");
1067 selOpt.value = "normal";
1068 selOpt.textContent = "Normal";
1069 boxsize.appendChild(selOpt);
1070 selOpt = document.createElement("option");
1071 selOpt.value = "small";
1072 selOpt.textContent = "Small";
1073 boxsize.appendChild(selOpt);
1074 selOpt = document.createElement("option");
1075 selOpt.value = "large";
1076 selOpt.textContent = "Large";
1077 boxsize.appendChild(selOpt);
1078 selOpt = document.createElement("option");
1079 selOpt.value = "huge";
1080 selOpt.textContent = "Huge";
1081 boxsize.appendChild(selOpt);
1082 span = document.createElement('span');
1083 span.textContent = "Response Text Area";
1084 div.appendChild(span);
1085 div.appendChild(boxsize);
1086 options.appendChild(div);
1087 if (popupInstance.dataTransfer.node != null)
1088 {
1089 tA.value = popupInstance.dataTransfer.node.question;
1090 document.getElementById("ID").value = popupInstance.dataTransfer.node.id;
1091 document.getElementById("mandatory").value = popupInstance.dataTransfer.node.mandatory;
1092 document.getElementById("boxsize").value = popupInstance.dataTransfer.node.boxsize;
1093 }
1094 break;
1095 case "number":
1096 var span = document.createElement('span');
1097 span.textContent = "Enter Question";
1098 var tA = document.createElement('textarea');
1099 tA.style.width = "460px";
1100 tA.style.height = "54px";
1101 tA.id = "question";
1102 options.appendChild(span);
1103 options.appendChild(tA);
1104 var div = document.createElement('div');
1105 var input = document.createElement('input');
1106 input.id = "ID";
1107 span = document.createElement('span');
1108 span.textContent = "ID:";
1109 div.appendChild(span);
1110 div.appendChild(input);
1111 options.appendChild(div);
1112 div = document.createElement('div');
1113 input = document.createElement('input');
1114 input.type = "checkbox";
1115 input.id = "mandatory";
1116 span = document.createElement('span');
1117 span.textContent = "Mandatory";
1118 div.appendChild(span);
1119 div.appendChild(input);
1120 options.appendChild(div);
1121 div = document.createElement('div');
1122 break;
1123 }
1124 };
1125 if (this.dataTransfer.node != null)
1126 {
1127 select.value = this.dataTransfer.node.type;
1128 }
1129 select.onchange();
1130 break;
1131 case 7:
1132 this.dataTransfer = null;
1133 this.popupTitleText.textContent = "Test Session - Pre/Post Survey";
1134 var span = document.createElement('span');
1135 span.textContent = "Add your pre test session and post test session survey options here";
1136 this.popupBody.appendChild(span);
1137 var preHolder = document.createElement('div');
1138 preHolder.id = "preHolder";
1139 preHolder.style.width = "460px";
1140 preHolder.style.minHeight = "100px";
1141 preHolder.style.maxHeight = "220px";
1142 preHolder.style.overflow = 'auto';
1143 preHolder.style.border = "black";
1144 preHolder.style.borderStyle = "solid";
1145 preHolder.style.borderWidth = "1px";
1146 this.popupBody.appendChild(preHolder);
1147 var preHeaderHolder = document.createElement('div');
1148 preHeaderHolder.style.width = "456px";
1149 preHeaderHolder.style.height= "20px";
1150 preHeaderHolder.style.margin= "2px";
1151 preHeaderHolder.style.borderBottom = "#DDD";
1152 preHeaderHolder.style.borderBottomWidth = "1px";
1153 preHeaderHolder.style.borderBottomStyle = "solid";
1154 var mvH = document.createElement('div');
1155 mvH.className = "dndheaderelement";
1156 mvH.style.width = "50px";
1157 var text = document.createElement('span');
1158 text.textContent = "Order";
1159 mvH.appendChild(text);
1160 preHeaderHolder.appendChild(mvH);
1161 var idH = document.createElement('div');
1162 idH.className = "dndheaderelement";
1163 idH.style.width = "150px";
1164 text = document.createElement('span');
1165 text.textContent = "ID";
1166 idH.appendChild(text);
1167 preHeaderHolder.appendChild(idH);
1168 var tH = document.createElement('div');
1169 tH.className = "dndheaderelement";
1170 tH.style.width = "150px";
1171 text = document.createElement('span');
1172 text.textContent = "Type";
1173 tH.appendChild(text);
1174 preHeaderHolder.appendChild(tH);
1175 var editH = document.createElement('div');
1176 editH.className = "dndheaderelement";
1177 editH.style.width = "50px";
1178 text = document.createElement('span');
1179 text.textContent = "Edit";
1180 editH.appendChild(text);
1181 preHeaderHolder.appendChild(editH);
1182 var deleteH = document.createElement('div');
1183 deleteH.className = "dndheaderelement";
1184 deleteH.style.width = "50px";
1185 text = document.createElement('span');
1186 text.textContent = "Delete";
1187 deleteH.appendChild(text);
1188 preHeaderHolder.appendChild(deleteH);
1189 preHolder.appendChild(preHeaderHolder);
1190
1191
1192 for (var i=0; i<specificationNode.preTest.options.length; i++)
1193 {
1194 var optionNode = specificationNode.preTest.options[i];
1195 var entry = document.createElement('div');
1196 entry.style.width = "456px";
1197 entry.style.height= "20px";
1198 entry.style.margin= "2px";
1199 entry.style.borderBottom = "#DDD";
1200 entry.style.borderBottomWidth = "1px";
1201 entry.style.borderBottomStyle = "solid";
1202 entry.setAttribute("node-id",i);
1203 var node = specificationNode.preTest.options[i];
1204 var mvH = document.createElement('div');
1205 mvH.className = "dndheaderelement";
1206 mvH.style.width = "50px";
1207 var mvup = document.createElement("button");
1208 mvup.textContent = "Up";
1209 mvup.style.width = "25px";
1210 mvup.style.padding = "1px 0px";
1211 mvup.onclick = function()
1212 {
1213 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1214 if (i != 0)
1215 {
1216 var next = specificationNode.preTest.options[i-1];
1217 var cur = specificationNode.preTest.options[i];
1218 specificationNode.preTest.options[i-1] = cur;
1219 specificationNode.preTest.options[i] = next;
1220 popupInstance.state = 7;
1221 popupInstance.advanceState();
1222 }
1223 };
1224 mvH.appendChild(mvup);
1225 var mvdn = document.createElement("button");
1226 mvdn.textContent = "Dn";
1227 mvdn.style.width = "25px";
1228 mvdn.style.padding = "1px 0px";
1229 mvdn.onclick = function()
1230 {
1231 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1232 if (i != specificationNode.preTest.options.length-1)
1233 {
1234 var next = specificationNode.preTest.options[i+1];
1235 var cur = specificationNode.preTest.options[i];
1236 specificationNode.preTest.options[i+1] = cur;
1237 specificationNode.preTest.options[i] = next;
1238 popupInstance.state = 7;
1239 popupInstance.advanceState();
1240 }
1241 };
1242 mvH.appendChild(mvdn);
1243 entry.appendChild(mvH);
1244 var idH = document.createElement('div');
1245 idH.className = "dndheaderelement";
1246 idH.style.width = "150px";
1247 if (optionNode.type != "statement")
1248 {
1249 var span = document.createElement('span');
1250 span.textContent = optionNode.id;
1251 idH.appendChild(span);
1252 }
1253 entry.appendChild(idH);
1254 var typeH = document.createElement('div');
1255 typeH.className = "dndheaderelement";
1256 typeH.style.width = "150px";
1257 var span = document.createElement('span');
1258 span.textContent = optionNode.type;
1259 typeH.appendChild(span);
1260 entry.appendChild(typeH);
1261 var editH = document.createElement('div');
1262 editH.className = "dndheaderelement";
1263 editH.style.width = "50px";
1264 var editButton = document.createElement("button");
1265 editButton.textContent = "Edit";
1266 editButton.style.width = "48px";
1267 editButton.style.padding = "1px 0px";
1268 editButton.onclick = function()
1269 {
1270 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1271 popupInstance.dataTransfer = new function() {
1272 this.title = "Edit Test Node";
1273 this.parent = specificationNode.preTest;
1274 this.node = this.parent.options[i];
1275 this.previousState = 7;
1276 };
1277 popupInstace.state = 6;
1278 popupInstance.advanceState();
1279 };
1280 editH.appendChild(editButton);
1281 entry.appendChild(editH);
1282 var deleteH = document.createElement('div');
1283 deleteH.className = "dndheaderelement";
1284 deleteH.style.width = "50px";
1285 var deleteButton = document.createElement("button");
1286 deleteButton.textContent = "Del";
1287 deleteButton.style.width = "48px";
1288 deleteButton.style.padding = "1px 0px";
1289 deleteButton.onclick = function()
1290 {
1291 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1292 var j = i+1;
1293 while(j < specificationNode.preTest.options.length)
1294 {
1295 specificationNode.preTest.options[i] = specificationNode.preTest.options[j];
1296 j++;
1297 i++;
1298 }
1299 specificationNode.preTest.options.pop();
1300 popupInstance.state = 7;
1301 popupInstance.advanceState();
1302 };
1303 deleteH.appendChild(deleteButton);
1304 entry.appendChild(deleteH);
1305 preHolder.appendChild(entry);
1306 }
1307 var entry = document.createElement('div');
1308 entry.style.width = "456px";
1309 entry.style.height= "20px";
1310 entry.style.margin= "2px";
1311 entry.style.borderBottom = "#DDD";
1312 entry.style.borderBottomWidth = "1px";
1313 entry.style.borderBottomStyle = "solid";
1314 entry.align = "center";
1315 var addPre = document.createElement('button');
1316 addPre.className = "popupButton";
1317 addPre.textContent = "Add New Entry";
1318 addPre.style.height = "20px";
1319 addPre.onclick = function()
1320 {
1321 popupInstance.dataTransfer = new function() {
1322 this.title = "New Pre Test Node";
1323 this.parent = specificationNode.preTest;
1324 this.node = null;
1325 this.previousState = 7;
1326 };
1327 popupInstance.state = 6;
1328 popupInstance.advanceState();
1329 };
1330 entry.appendChild(addPre);
1331 preHolder.appendChild(entry);
1332
1333 var span = document.createElement('span');
1334 span.textContent = "Add your post test page options here";
1335 this.popupBody.appendChild(span);
1336 var postHolder = document.createElement('div');
1337 postHolder.id = "preHolder";
1338 postHolder.style.width = "100%";
1339 postHolder.style.minHeight = "100px";
1340 postHolder.style.maxHeight = "220px";
1341 postHolder.style.overflow = 'auto';
1342 postHolder.style.border = "black";
1343 postHolder.style.borderStyle = "solid";
1344 postHolder.style.borderWidth = "1px";
1345 this.popupBody.appendChild(postHolder);
1346 var postHeaderHolder = document.createElement('div');
1347 postHeaderHolder.style.width = "456px";
1348 postHeaderHolder.style.height= "20px";
1349 postHeaderHolder.style.margin= "2px";
1350 postHeaderHolder.style.borderBottom = "#DDD";
1351 postHeaderHolder.style.borderBottomWidth = "1px";
1352 postHeaderHolder.style.borderBottomStyle = "solid";
1353 var mvH = document.createElement('div');
1354 mvH.className = "dndheaderelement";
1355 mvH.style.width = "50px";
1356 var text = document.createElement('span');
1357 text.textContent = "Order";
1358 mvH.appendChild(text);
1359 postHeaderHolder.appendChild(mvH);
1360 var idH = document.createElement('div');
1361 idH.className = "dndheaderelement";
1362 idH.style.width = "150px";
1363 text = document.createElement('span');
1364 text.textContent = "ID";
1365 idH.appendChild(text);
1366 postHeaderHolder.appendChild(idH);
1367 var tH = document.createElement('div');
1368 tH.className = "dndheaderelement";
1369 tH.style.width = "150px";
1370 text = document.createElement('span');
1371 text.textContent = "Type";
1372 tH.appendChild(text);
1373 postHeaderHolder.appendChild(tH);
1374 var editH = document.createElement('div');
1375 editH.className = "dndheaderelement";
1376 editH.style.width = "50px";
1377 text = document.createElement('span');
1378 text.textContent = "Edit";
1379 editH.appendChild(text);
1380 postHeaderHolder.appendChild(editH);
1381 var deleteH = document.createElement('div');
1382 deleteH.className = "dndheaderelement";
1383 deleteH.style.width = "50px";
1384 text = document.createElement('span');
1385 text.textContent = "Delete";
1386 deleteH.appendChild(text);
1387 postHeaderHolder.appendChild(deleteH);
1388 postHolder.appendChild(postHeaderHolder);
1389
1390 for (var i=0; i<specificationNode.postTest.options.length; i++)
1391 {
1392 var optionNode = specificationNode.postTest.options[i];
1393 var entry = document.createElement('div');
1394 entry.style.width = "456px";
1395 entry.style.height= "20px";
1396 entry.style.margin= "2px";
1397 entry.style.borderBottom = "#DDD";
1398 entry.style.borderBottomWidth = "1px";
1399 entry.style.borderBottomStyle = "solid";
1400 entry.setAttribute("node-id",i);
1401 var node = specificationNode.postTest.options[i];
1402 var mvH = document.createElement('div');
1403 mvH.className = "dndheaderelement";
1404 mvH.style.width = "50px";
1405 var mvup = document.createElement("button");
1406 mvup.textContent = "Up";
1407 mvup.style.width = "25px";
1408 mvup.style.padding = "1px 0px";
1409 mvup.onclick = function()
1410 {
1411 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1412 if (i != 0)
1413 {
1414 var next = specificationNode.postTest.options[i-1];
1415 var cur = specificationNode.postTest.options[i];
1416 specificationNode.postTest.options[i-1] = cur;
1417 specificationNode.postTest.options[i] = next;
1418 popupInstance.state = 7;
1419 popupInstance.advanceState();
1420 }
1421 };
1422 mvH.appendChild(mvup);
1423 var mvdn = document.createElement("button");
1424 mvdn.textContent = "Dn";
1425 mvdn.style.width = "25px";
1426 mvdn.style.padding = "1px 0px";
1427 mvdn.onclick = function()
1428 {
1429 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1430 if (i != specificationNode.postTest.options.length-1)
1431 {
1432 var next = specificationNode.postTest.options[i+1];
1433 var cur = specificationNode.postTest.options[i];
1434 specificationNode.postTest.options[i+1] = cur;
1435 specificationNode.postTest.options[i] = next;
1436 popupInstance.state = 7;
1437 popupInstance.advanceState();
1438 }
1439 };
1440 mvH.appendChild(mvdn);
1441 entry.appendChild(mvH);
1442 var idH = document.createElement('div');
1443 idH.className = "dndheaderelement";
1444 idH.style.width = "150px";
1445 if (optionNode.type != "statement")
1446 {
1447 var span = document.createElement('span');
1448 span.textContent = optionNode.id;
1449 idH.appendChild(span);
1450 }
1451 entry.appendChild(idH);
1452 var typeH = document.createElement('div');
1453 typeH.className = "dndheaderelement";
1454 typeH.style.width = "150px";
1455 var span = document.createElement('span');
1456 span.textContent = optionNode.type;
1457 typeH.appendChild(span);
1458 entry.appendChild(typeH);
1459 var editH = document.createElement('div');
1460 editH.className = "dndheaderelement";
1461 editH.style.width = "50px";
1462 var editButton = document.createElement("button");
1463 editButton.textContent = "Edit";
1464 editButton.style.width = "48px";
1465 editButton.style.padding = "1px 0px";
1466 editButton.onclick = function()
1467 {
1468 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1469 popupInstance.dataTransfer = new function() {
1470 this.title = "Edit Test Node";
1471 this.parent = specificationNode.postTest;
1472 this.node = this.parent.options[i];
1473 this.previousState = 7;
1474 };
1475 popupInstance.state = 6;
1476 popupInstance.advanceState();
1477 };
1478 editH.appendChild(editButton);
1479 entry.appendChild(editH);
1480 var deleteH = document.createElement('div');
1481 deleteH.className = "dndheaderelement";
1482 deleteH.style.width = "50px";
1483 var deleteButton = document.createElement("button");
1484 deleteButton.textContent = "Del";
1485 deleteButton.style.width = "48px";
1486 deleteButton.style.padding = "1px 0px";
1487 deleteButton.onclick = function()
1488 {
1489 var i = Number(event.currentTarget.parentElement.parentElement.getAttribute("node-id"));
1490 var j = i+1;
1491 while(j < specificationNode.postTest.options.length)
1492 {
1493 specificationNode.postTest.options[i] = specificationNode.postTest.options[j];
1494 j++;
1495 i++;
1496 }
1497 audioHolder.postTest.options.pop();
1498 popupInstance.state = 7;
1499 popupInstance.advanceState();
1500 };
1501 deleteH.appendChild(deleteButton);
1502 entry.appendChild(deleteH);
1503 postHolder.appendChild(entry);
1504 }
1505
1506 var entry = document.createElement('div');
1507 entry.style.width = "456px";
1508 entry.style.height= "20px";
1509 entry.style.margin= "2px";
1510 entry.style.borderBottom = "#DDD";
1511 entry.style.borderBottomWidth = "1px";
1512 entry.style.borderBottomStyle = "solid";
1513 entry.align = "center";
1514 var addPost = document.createElement('button');
1515 addPost.className = "popupButton";
1516 addPost.textContent = "Add New Entry";
1517 addPost.style.height = "20px";
1518 addPost.onclick = function()
1519 {
1520 popupInstance.dataTransfer = new function() {
1521 this.title = "New Pre Test Node";
1522 this.parent = specificationNode.postTest;
1523 this.node = null;
1524 this.previousState = 7;
1525 };
1526 popupInstance.state = 6;
1527 popupInstance.advanceState();
1528 };
1529 entry.appendChild(addPost);
1530 postHolder.appendChild(entry);
1531
1532 var button = document.createElement('button');
1533 button.id = 'submit';
1534 button.className = "popupButton";
1535 button.textContent = "Finish";
1536 button.onclick = function(event)
1537 {
1538 popupInstance.state = 8;
1539 popupInstance.advanceState();
1540 };
1541 this.popupFooter.appendChild(button);
1542 break;
1543 case 8:
1544 this.hidePopup();
1545 this.state = 0;
1546 SpecificationToHTML ();
1547 }
1548 this.state++;
1549 };
1550 };
1551
1552 function audioObject()
1553 {
1554 // Used to hold audio information in buffers for quick playback
1555 this.bufferObject;
1556 this.bufferNode = undefined;
1557 this.state = 0;
1558 this.gain = audioContext.createGain();
1559 this.gain.connect(audioContext.destination);
1560 this.include = true;
1561 this.id = undefined;
1562 this.file = undefined;
1563
1564 this.play = function()
1565 {
1566 if (this.bufferNode != undefined)
1567 {
1568 this.bufferNode.stop(0);
1569 this.bufferNode = undefined;
1570 }
1571 if(this.state == 1)
1572 {
1573 this.bufferNode = audioContext.createBufferSource();
1574 this.bufferNode.connect(this.gain);
1575 this.bufferNode.buffer = this.bufferObject;
1576 this.bufferNode.onended = function(event) {
1577 // Safari does not like using 'this' to reference the calling object!
1578 event.currentTarget = undefined;
1579 };
1580 this.bufferNode.start(audioContext.currentTime);
1581 this.bufferNode.stop(audioContext.currentTime+3);
1582 }
1583 };
1584
1585 this.constructTrack = function(file) {
1586 var reader = new FileReader();
1587 this.file = file;
1588 var audioObj = this;
1589 // Create callback to decode the data asynchronously
1590 reader.onloadend = function() {
1591 audioContext.decodeAudioData(reader.result, function(decodedData) {
1592 audioObj.bufferObject = decodedData;
1593 audioObj.state = 1;
1594 }, function(){});
1595 };
1596 reader.readAsArrayBuffer(file);
1597 };
1598 };
1599
1600 function Specification() {
1601 // Handles the decoding of the project specification XML into a simple JavaScript Object.
1602
1603 this.interfaceType = null;
1604 this.commonInterface = new function()
1605 {
1606 this.options = [];
1607 this.optionNode = function(input)
1608 {
1609 var name = input.getAttribute('name');
1610 this.type = name;
1611 if(this.type == "option")
1612 {
1613 this.name = input.id;
1614 } else if (this.type == "check")
1615 {
1616 this.check = input.id;
1617 }
1618 };
1619 };
1620
1621 this.randomiseOrder = function(input)
1622 {
1623 // This takes an array of information and randomises the order
1624 var N = input.length;
1625
1626 var inputSequence = []; // For safety purposes: keep track of randomisation
1627 for (var counter = 0; counter < N; ++counter)
1628 inputSequence.push(counter) // Fill array
1629 var inputSequenceClone = inputSequence.slice(0);
1630
1631 var holdArr = [];
1632 var outputSequence = [];
1633 for (var n=0; n<N; n++)
1634 {
1635 // First pick a random number
1636 var r = Math.random();
1637 // Multiply and floor by the number of elements left
1638 r = Math.floor(r*input.length);
1639 // Pick out that element and delete from the array
1640 holdArr.push(input.splice(r,1)[0]);
1641 // Do the same with sequence
1642 outputSequence.push(inputSequence.splice(r,1)[0]);
1643 }
1644 console.log(inputSequenceClone.toString()); // print original array to console
1645 console.log(outputSequence.toString()); // print randomised array to console
1646 return holdArr;
1647 };
1648 this.projectReturn = null;
1649 this.randomiseOrder = null;
1650 this.collectMetrics = null;
1651 this.testPages = null;
1652 this.audioHolders = [];
1653 this.metrics = [];
1654
1655 this.decode = function(projectXML) {
1656 // projectXML - DOM Parsed document
1657 this.projectXML = projectXML.childNodes[0];
1658 var setupNode = projectXML.getElementsByTagName('setup')[0];
1659 this.interfaceType = setupNode.getAttribute('interface');
1660 this.projectReturn = setupNode.getAttribute('projectReturn');
1661 this.testPages = setupNode.getAttribute('testPages');
1662 if (setupNode.getAttribute('randomiseOrder') == "true") {
1663 this.randomiseOrder = true;
1664 } else {this.randomiseOrder = false;}
1665 if (setupNode.getAttribute('collectMetrics') == "true") {
1666 this.collectMetrics = true;
1667 } else {this.collectMetrics = false;}
1668 if (isNaN(Number(this.testPages)) || this.testPages == undefined)
1669 {
1670 this.testPages = null;
1671 } else {
1672 this.testPages = Number(this.testPages);
1673 if (this.testPages == 0) {this.testPages = null;}
1674 }
1675 var metricCollection = setupNode.getElementsByTagName('Metric');
1676
1677 var setupPreTestNode = setupNode.getElementsByTagName('PreTest');
1678 if (setupPreTestNode.length != 0)
1679 {
1680 setupPreTestNode = setupPreTestNode[0];
1681 this.preTest.construct(setupPreTestNode);
1682 }
1683
1684 var setupPostTestNode = setupNode.getElementsByTagName('PostTest');
1685 if (setupPostTestNode.length != 0)
1686 {
1687 setupPostTestNode = setupPostTestNode[0];
1688 this.postTest.construct(setupPostTestNode);
1689 }
1690
1691 if (metricCollection.length > 0) {
1692 metricCollection = metricCollection[0].getElementsByTagName('metricEnable');
1693 for (var i=0; i<metricCollection.length; i++) {
1694 this.metrics.push(new this.metricNode(metricCollection[i].textContent));
1695 }
1696 }
1697
1698 var commonInterfaceNode = setupNode.getElementsByTagName('interface');
1699 if (commonInterfaceNode.length > 0) {
1700 commonInterfaceNode = commonInterfaceNode[0];
1701 } else {
1702 commonInterfaceNode = undefined;
1703 }
1704
1705 this.commonInterface = new function() {
1706 this.OptionNode = function(child) {
1707 this.type = child.nodeName;
1708 if (this.type == 'option')
1709 {
1710 this.name = child.getAttribute('name');
1711 }
1712 else if (this.type == 'check') {
1713 this.check = child.getAttribute('name');
1714 if (this.check == 'scalerange') {
1715 this.min = child.getAttribute('min');
1716 this.max = child.getAttribute('max');
1717 if (this.min == null) {this.min = 1;}
1718 else if (Number(this.min) > 1 && this.min != null) {
1719 this.min = Number(this.min)/100;
1720 } else {
1721 this.min = Number(this.min);
1722 }
1723 if (this.max == null) {this.max = 0;}
1724 else if (Number(this.max) > 1 && this.max != null) {
1725 this.max = Number(this.max)/100;
1726 } else {
1727 this.max = Number(this.max);
1728 }
1729 }
1730 } else if (this.type == 'anchor' || this.type == 'reference') {
1731 this.value = Number(child.textContent);
1732 this.enforce = child.getAttribute('enforce');
1733 if (this.enforce == 'true') {this.enforce = true;}
1734 else {this.enforce = false;}
1735 }
1736 };
1737 this.options = [];
1738 if (commonInterfaceNode != undefined) {
1739 var child = commonInterfaceNode.firstElementChild;
1740 while (child != undefined) {
1741 this.options.push(new this.OptionNode(child));
1742 child = child.nextElementSibling;
1743 }
1744 }
1745 };
1746
1747 var audioHolders = projectXML.getElementsByTagName('audioHolder');
1748 for (var i=0; i<audioHolders.length; i++) {
1749 var node = new this.audioHolderNode(this);
1750 node.decode(this,audioHolders[i]);
1751 this.audioHolders.push(node);
1752 }
1753
1754 // New check if we need to randomise the test order
1755 if (this.randomiseOrder && typeof randomiseOrder === "function")
1756 {
1757 this.audioHolders = randomiseOrder(this.audioHolders);
1758 for (var i=0; i<this.audioHolders.length; i++)
1759 {
1760 this.audioHolders[i].presentedId = i;
1761 }
1762 }
1763
1764 if (this.testPages != null || this.testPages != undefined)
1765 {
1766 if (this.testPages > audioHolders.length)
1767 {
1768 console.log('Warning: You have specified '+audioHolders.length+' tests but requested '+this.testPages+' be completed!');
1769 this.testPages = audioHolders.length;
1770 }
1771 var aH = this.audioHolders;
1772 this.audioHolders = [];
1773 for (var i=0; i<this.testPages; i++)
1774 {
1775 this.audioHolders.push(aH[i]);
1776 }
1777 }
1778 };
1779
1780 this.encode = function()
1781 {
1782 var root = document.implementation.createDocument(null,"BrowserEvalProjectDocument");
1783 // First get all the <setup> tag compiled
1784 var setupNode = root.createElement("setup");
1785 setupNode.setAttribute('interface',this.interfaceType);
1786 setupNode.setAttribute('projectReturn',this.projectReturn);
1787 setupNode.setAttribute('randomiseOrder',this.randomiseOrder);
1788 setupNode.setAttribute('collectMetrics',this.collectMetrics);
1789 setupNode.setAttribute('testPages',this.testPages);
1790
1791 var setupPreTest = root.createElement("PreTest");
1792 for (var i=0; i<this.preTest.options.length; i++)
1793 {
1794 setupPreTest.appendChild(this.preTest.options[i].exportXML(root));
1795 }
1796
1797 var setupPostTest = root.createElement("PostTest");
1798 for (var i=0; i<this.postTest.options.length; i++)
1799 {
1800 setupPostTest.appendChild(this.postTest.options[i].exportXML(root));
1801 }
1802
1803 setupNode.appendChild(setupPreTest);
1804 setupNode.appendChild(setupPostTest);
1805
1806 // <Metric> tag
1807 var Metric = root.createElement("Metric");
1808 for (var i=0; i<this.metrics.length; i++)
1809 {
1810 var metricEnable = root.createElement("metricEnable");
1811 metricEnable.textContent = this.metrics[i].enabled;
1812 Metric.appendChild(metricEnable);
1813 }
1814 setupNode.appendChild(Metric);
1815
1816 // <interface> tag
1817 var CommonInterface = root.createElement("interface");
1818 for (var i=0; i<this.commonInterface.options.length; i++)
1819 {
1820 var CIObj = this.commonInterface.options[i];
1821 var CINode = root.createElement(CIObj.type);
1822 if (CIObj.type == "check") {CINode.setAttribute("name",CIObj.check);}
1823 else {CINode.setAttribute("name",CIObj.name);}
1824 CommonInterface.appendChild(CINode);
1825 }
1826 setupNode.appendChild(CommonInterface);
1827
1828 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(setupNode);
1829 // Time for the <audioHolder> tags
1830 for (var ahIndex = 0; ahIndex < this.audioHolders.length; ahIndex++)
1831 {
1832 var node = this.audioHolders[ahIndex].encode(root);
1833 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(node);
1834 }
1835 return root;
1836 };
1837
1838 this.prepostNode = function(type) {
1839 this.type = type;
1840 this.options = [];
1841
1842 this.OptionNode = function() {
1843
1844 this.childOption = function() {
1845 this.type = 'option';
1846 this.id = null;
1847 this.name = undefined;
1848 this.text = null;
1849 };
1850
1851 this.type = undefined;
1852 this.id = undefined;
1853 this.mandatory = undefined;
1854 this.question = undefined;
1855 this.statement = undefined;
1856 this.boxsize = undefined;
1857 this.options = [];
1858 this.min = undefined;
1859 this.max = undefined;
1860 this.step = undefined;
1861
1862 this.decode = function(child)
1863 {
1864 this.type = child.nodeName;
1865 if (child.nodeName == "question") {
1866 this.id = child.id;
1867 this.mandatory;
1868 if (child.getAttribute('mandatory') == "true") {this.mandatory = true;}
1869 else {this.mandatory = false;}
1870 this.question = child.textContent;
1871 if (child.getAttribute('boxsize') == null) {
1872 this.boxsize = 'normal';
1873 } else {
1874 this.boxsize = child.getAttribute('boxsize');
1875 }
1876 } else if (child.nodeName == "statement") {
1877 this.statement = child.textContent;
1878 } else if (child.nodeName == "checkbox" || child.nodeName == "radio") {
1879 var element = child.firstElementChild;
1880 this.id = child.id;
1881 if (element == null) {
1882 console.log('Malformed' +child.nodeName+ 'entry');
1883 this.statement = 'Malformed' +child.nodeName+ 'entry';
1884 this.type = 'statement';
1885 } else {
1886 this.options = [];
1887 while (element != null) {
1888 if (element.nodeName == 'statement' && this.statement == undefined){
1889 this.statement = element.textContent;
1890 } else if (element.nodeName == 'option') {
1891 var node = new this.childOption();
1892 node.id = element.id;
1893 node.name = element.getAttribute('name');
1894 node.text = element.textContent;
1895 this.options.push(node);
1896 }
1897 element = element.nextElementSibling;
1898 }
1899 }
1900 } else if (child.nodeName == "number") {
1901 this.statement = child.textContent;
1902 this.id = child.id;
1903 this.min = child.getAttribute('min');
1904 this.max = child.getAttribute('max');
1905 this.step = child.getAttribute('step');
1906 }
1907 };
1908
1909 this.exportXML = function(root)
1910 {
1911 var node = root.createElement(this.type);
1912 switch(this.type)
1913 {
1914 case "statement":
1915 node.textContent = this.statement;
1916 break;
1917 case "question":
1918 node.id = this.id;
1919 node.setAttribute("mandatory",this.mandatory);
1920 node.setAttribute("boxsize",this.boxsize);
1921 node.textContent = this.question;
1922 break;
1923 case "number":
1924 node.id = this.id;
1925 node.setAttribute("mandatory",this.mandatory);
1926 node.setAttribute("min", this.min);
1927 node.setAttribute("max", this.max);
1928 node.setAttribute("step", this.step);
1929 node.textContent = this.statement;
1930 break;
1931 case "checkbox":
1932 node.id = this.id;
1933 var statement = root.createElement("statement");
1934 statement.textContent = this.statement;
1935 node.appendChild(statement);
1936 for (var i=0; i<this.options.length; i++)
1937 {
1938 var option = this.options[i];
1939 var optionNode = root.createElement("option");
1940 optionNode.id = option.id;
1941 optionNode.textContent = option.text;
1942 node.appendChild(optionNode);
1943 }
1944 break;
1945 case "radio":
1946 node.id = this.id;
1947 var statement = root.createElement("statement");
1948 statement.textContent = this.statement;
1949 node.appendChild(statement);
1950 for (var i=0; i<this.options.length; i++)
1951 {
1952 var option = this.options[i];
1953 var optionNode = root.createElement("option");
1954 optionNode.setAttribute("name",option.name);
1955 optionNode.textContent = option.text;
1956 node.appendChild(optionNode);
1957 }
1958 break;
1959 }
1960 return node;
1961 };
1962 };
1963 this.construct = function(Collection)
1964 {
1965 if (Collection.childElementCount != 0) {
1966 var child = Collection.firstElementChild;
1967 var node = new this.OptionNode();
1968 node.decode(child);
1969 this.options.push(node);
1970 while (child.nextElementSibling != null) {
1971 child = child.nextElementSibling;
1972 node = new this.OptionNode();
1973 node.decode(child);
1974 this.options.push(node);
1975 }
1976 }
1977 };
1978 };
1979 this.preTest = new this.prepostNode("pretest");
1980 this.postTest = new this.prepostNode("posttest");
1981
1982 this.metricNode = function(name) {
1983 this.enabled = name;
1984 };
1985
1986 this.audioHolderNode = function(parent) {
1987 this.type = 'audioHolder';
1988 this.presentedId = undefined;
1989 this.id = undefined;
1990 this.hostURL = undefined;
1991 this.sampleRate = undefined;
1992 this.randomiseOrder = undefined;
1993 this.loop = undefined;
1994 this.elementComments = undefined;
1995 this.outsideReference = null;
1996 this.preTest = new parent.prepostNode("pretest");
1997 this.postTest = new parent.prepostNode("pretest");
1998 this.interfaces = [];
1999 this.commentBoxPrefix = "Comment on track";
2000 this.audioElements = [];
2001 this.commentQuestions = [];
2002
2003 this.decode = function(parent,xml)
2004 {
2005 this.presentedId = parent.audioHolders.length;
2006 this.id = xml.id;
2007 this.hostURL = xml.getAttribute('hostURL');
2008 this.sampleRate = xml.getAttribute('sampleRate');
2009 if (xml.getAttribute('randomiseOrder') == "true") {this.randomiseOrder = true;}
2010 else {this.randomiseOrder = false;}
2011 this.repeatCount = xml.getAttribute('repeatCount');
2012 if (xml.getAttribute('loop') == 'true') {this.loop = true;}
2013 else {this.loop == false;}
2014 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;}
2015 else {this.elementComments = false;}
2016
2017 var setupPreTestNode = xml.getElementsByTagName('PreTest');
2018 if (setupPreTestNode.length != 0)
2019 {
2020 setupPreTestNode = setupPreTestNode[0];
2021 this.preTest.construct(setupPreTestNode);
2022 }
2023
2024 var setupPostTestNode = xml.getElementsByTagName('PostTest');
2025 if (setupPostTestNode.length != 0)
2026 {
2027 setupPostTestNode = setupPostTestNode[0];
2028 this.postTest.construct(setupPostTestNode);
2029 }
2030
2031 var interfaceDOM = xml.getElementsByTagName('interface');
2032 for (var i=0; i<interfaceDOM.length; i++) {
2033 var node = new this.interfaceNode();
2034 node.decode(interfaceDOM[i]);
2035 this.interfaces.push(node);
2036 }
2037 this.commentBoxPrefix = xml.getElementsByTagName('commentBoxPrefix');
2038 if (this.commentBoxPrefix.length != 0) {
2039 this.commentBoxPrefix = this.commentBoxPrefix[0].textContent;
2040 } else {
2041 this.commentBoxPrefix = "Comment on track";
2042 }
2043 var audioElementsDOM = xml.getElementsByTagName('audioElements');
2044 for (var i=0; i<audioElementsDOM.length; i++) {
2045 var node = new this.audioElementNode();
2046 node.decode(this,audioElementsDOM[i]);
2047 if (audioElementsDOM[i].getAttribute('type') == 'outsidereference') {
2048 if (this.outsideReference == null) {
2049 this.outsideReference = node;
2050 } else {
2051 console.log('Error only one audioelement can be of type outsidereference per audioholder');
2052 this.audioElements.push(node);
2053 console.log('Element id '+audioElementsDOM[i].id+' made into normal node');
2054 }
2055 } else {
2056 this.audioElements.push(node);
2057 }
2058 }
2059
2060 if (this.randomiseOrder == true && typeof randomiseOrder === "function")
2061 {
2062 this.audioElements = randomiseOrder(this.audioElements);
2063 }
2064
2065 var commentQuestionsDOM = xml.getElementsByTagName('CommentQuestion');
2066 for (var i=0; i<commentQuestionsDOM.length; i++) {
2067 var node = new this.commentQuestionNode();
2068 node.decode(commentQuestionsDOM[i]);
2069 this.commentQuestions.push(node);
2070 }
2071 };
2072
2073 this.encode = function(root)
2074 {
2075 var AHNode = root.createElement("audioHolder");
2076 AHNode.id = this.id;
2077 AHNode.setAttribute("hostURL",this.hostURL);
2078 AHNode.setAttribute("sampleRate",this.sampleRate);
2079 AHNode.setAttribute("randomiseOrder",this.randomiseOrder);
2080 AHNode.setAttribute("repeatCount",this.repeatCount);
2081 AHNode.setAttribute("loop",this.loop);
2082 AHNode.setAttribute("elementComments",this.elementComments);
2083
2084 for (var i=0; i<this.interfaces.length; i++)
2085 {
2086 AHNode.appendChild(this.interfaces[i].encode(root));
2087 }
2088
2089 for (var i=0; i<this.audioElements.length; i++) {
2090 AHNode.appendChild(this.audioElements[i].encode(root));
2091 }
2092 // Create <CommentQuestion>
2093 for (var i=0; i<this.commentQuestions.length; i++)
2094 {
2095 AHNode.appendChild(this.commentQuestions[i].exportXML(root));
2096 }
2097
2098 // Create <PreTest>
2099 var AHPreTest = root.createElement("PreTest");
2100 for (var i=0; i<this.preTest.options.length; i++)
2101 {
2102 AHPreTest.appendChild(this.preTest.options[i].exportXML(root));
2103 }
2104
2105 var AHPostTest = root.createElement("PostTest");
2106 for (var i=0; i<this.postTest.options.length; i++)
2107 {
2108 AHPostTest.appendChild(this.postTest.options[i].exportXML(root));
2109 }
2110 AHNode.appendChild(AHPreTest);
2111 AHNode.appendChild(AHPostTest);
2112 return AHNode;
2113 };
2114
2115 this.interfaceNode = function() {
2116 this.title = undefined;
2117 this.options = [];
2118 this.scale = [];
2119 this.name = undefined;
2120 this.decode = function(DOM)
2121 {
2122 var title = DOM.getElementsByTagName('title');
2123 if (title.length == 0) {this.title = null;}
2124 else {this.title = title[0].textContent;}
2125 var name = DOM.getAttribute("name");
2126 if (name != undefined) {this.name = name;}
2127 this.options = parent.commonInterface.options;
2128 var scale = DOM.getElementsByTagName('scale');
2129 this.scale = [];
2130 for (var i=0; i<scale.length; i++) {
2131 var arr = [null, null];
2132 arr[0] = scale[i].getAttribute('position');
2133 arr[1] = scale[i].textContent;
2134 this.scale.push(arr);
2135 }
2136 };
2137 this.encode = function(root)
2138 {
2139 var node = root.createElement("interface");
2140 if (this.title != undefined)
2141 {
2142 var title = root.createElement("title");
2143 title.textContent = this.title;
2144 node.appendChild(title);
2145 }
2146 for (var i=0; i<this.options.length; i++)
2147 {
2148 var optionNode = root.createElement(this.options[i].type);
2149 if (this.options[i].type == "option")
2150 {
2151 optionNode.setAttribute("name",this.options[i].name);
2152 } else if (this.options[i].type == "check") {
2153 optionNode.setAttribute("check",this.options[i].check);
2154 } else if (this.options[i].type == "scalerange") {
2155 optionNode.setAttribute("min",this.options[i].min*100);
2156 optionNode.setAttribute("max",this.options[i].max*100);
2157 }
2158 node.appendChild(optionNode);
2159 }
2160 for (var i=0; i<this.scale.length; i++) {
2161 var scale = root.createElement("scale");
2162 scale.setAttribute("position",this.scale[i][0]);
2163 scale.textContent = this.scale[i][1];
2164 node.appendChild(scale);
2165 }
2166 return node;
2167 };
2168 };
2169
2170 this.audioElementNode = function() {
2171 this.url = null;
2172 this.id = null;
2173 this.parent = null;
2174 this.type = "normal";
2175 this.marker = false;
2176 this.enforce = false;
2177 this.gain = 1.0;
2178 this.decode = function(parent,xml)
2179 {
2180 this.url = xml.getAttribute('url');
2181 this.id = xml.id;
2182 this.parent = parent;
2183 this.type = xml.getAttribute('type');
2184 var gain = xml.getAttribute('gain');
2185 if (isNaN(gain) == false && gain != null)
2186 {
2187 this.gain = decibelToLinear(Number(gain));
2188 }
2189 if (this.type == null) {this.type = "normal";}
2190 if (this.type == 'anchor') {this.anchor = true;}
2191 else {this.anchor = false;}
2192 if (this.type == 'reference') {this.reference = true;}
2193 else {this.reference = false;}
2194 if (this.anchor == true || this.reference == true)
2195 {
2196 this.marker = xml.getAttribute('marker');
2197 if (this.marker != undefined)
2198 {
2199 this.marker = Number(this.marker);
2200 if (isNaN(this.marker) == false)
2201 {
2202 if (this.marker > 1)
2203 { this.marker /= 100.0;}
2204 if (this.marker >= 0 && this.marker <= 1)
2205 {
2206 this.enforce = true;
2207 return;
2208 } else {
2209 console.log("ERROR - Marker of audioElement "+this.id+" is not between 0 and 1 (float) or 0 and 100 (integer)!");
2210 console.log("ERROR - Marker not enforced!");
2211 }
2212 } else {
2213 console.log("ERROR - Marker of audioElement "+this.id+" is not a number!");
2214 console.log("ERROR - Marker not enforced!");
2215 }
2216 }
2217 }
2218 };
2219 this.encode = function(root)
2220 {
2221 var AENode = root.createElement("audioElements");
2222 AENode.id = this.id;
2223 AENode.setAttribute("url",this.url);
2224 AENode.setAttribute("type",this.type);
2225 AENode.setAttribute("gain",linearToDecibel(this.gain));
2226 if (this.marker != false)
2227 {
2228 AENode.setAttribute("marker",this.marker*100);
2229 }
2230 return AENode;
2231 };
2232 };
2233
2234 this.commentQuestionNode = function(xml) {
2235 this.id = null;
2236 this.type = undefined;
2237 this.question = undefined;
2238 this.options = [];
2239 this.statement = undefined;
2240
2241 this.childOption = function() {
2242 this.type = 'option';
2243 this.name = null;
2244 this.text = null;
2245 };
2246 this.exportXML = function(root)
2247 {
2248 var CQNode = root.createElement("CommentQuestion");
2249 CQNode.id = this.id;
2250 CQNode.setAttribute("type",this.type);
2251 switch(this.type)
2252 {
2253 case "text":
2254 CQNode.textContent = this.question;
2255 break;
2256 case "radio":
2257 var statement = root.createElement("statement");
2258 statement.textContent = this.statement;
2259 CQNode.appendChild(statement);
2260 for (var i=0; i<this.options.length; i++)
2261 {
2262 var optionNode = root.createElement("option");
2263 optionNode.setAttribute("name",this.options[i].name);
2264 optionNode.textContent = this.options[i].text;
2265 CQNode.appendChild(optionNode);
2266 }
2267 break;
2268 case "checkbox":
2269 var statement = root.createElement("statement");
2270 statement.textContent = this.statement;
2271 CQNode.appendChild(statement);
2272 for (var i=0; i<this.options.length; i++)
2273 {
2274 var optionNode = root.createElement("option");
2275 optionNode.setAttribute("name",this.options[i].name);
2276 optionNode.textContent = this.options[i].text;
2277 CQNode.appendChild(optionNode);
2278 }
2279 break;
2280 }
2281 return CQNode;
2282 };
2283 this.decode = function(xml) {
2284 this.id = xml.id;
2285 if (xml.getAttribute('mandatory') == 'true') {this.mandatory = true;}
2286 else {this.mandatory = false;}
2287 this.type = xml.getAttribute('type');
2288 if (this.type == undefined) {this.type = 'text';}
2289 switch (this.type) {
2290 case 'text':
2291 this.question = xml.textContent;
2292 break;
2293 case 'radio':
2294 var child = xml.firstElementChild;
2295 this.options = [];
2296 while (child != undefined) {
2297 if (child.nodeName == 'statement' && this.statement == undefined) {
2298 this.statement = child.textContent;
2299 } else if (child.nodeName == 'option') {
2300 var node = new this.childOption();
2301 node.name = child.getAttribute('name');
2302 node.text = child.textContent;
2303 this.options.push(node);
2304 }
2305 child = child.nextElementSibling;
2306 }
2307 break;
2308 case 'checkbox':
2309 var child = xml.firstElementChild;
2310 this.options = [];
2311 while (child != undefined) {
2312 if (child.nodeName == 'statement' && this.statement == undefined) {
2313 this.statement = child.textContent;
2314 } else if (child.nodeName == 'option') {
2315 var node = new this.childOption();
2316 node.name = child.getAttribute('name');
2317 node.text = child.textContent;
2318 this.options.push(node);
2319 }
2320 child = child.nextElementSibling;
2321 }
2322 break;
2323 }
2324 };
2325 };
2326 };
2327 }
2328
2329 function linearToDecibel(gain)
2330 {
2331 return 20.0*Math.log10(gain);
2332 }
2333
2334 function decibelToLinear(gain)
2335 {
2336 return Math.pow(10,gain/20.0);
2337 }
2338
2339 function createDeleteNodeButton(node)
2340 {
2341 var button = document.createElement("button");
2342 button.textContent = "Delete";
2343 button.onclick = function(event)
2344 {
2345 var node = event.target.parentElement;
2346 node.parentElement.removeChild(node);
2347 };
2348 return button;
2349 }
2350
2351 function SpecificationToHTML()
2352 {
2353 // Take information from Specification Node and format it into an HTML layout
2354 var destination = document.getElementById("content");
2355 // Setup Header Node
2356 var setupNode = document.createElement("div");
2357 setupNode.className = "topLevel";
2358 setupNode.name = "setup";
2359 var title = document.createElement("h2");
2360 title.textContent = "Setup";
2361 setupNode.appendChild(title);
2362 // Interface Type
2363 var div = document.createElement("div");
2364 div.name = "attributes";
2365 div.style.margin = "5px";
2366 var select = document.createElement("select");
2367 select.id = "interfaceSelect";
2368 select.style.margin = "5px";
2369 var option = document.createElement("option");
2370 option.value = "APE";
2371 option.textContent = "APE";
2372 select.appendChild(option);
2373 option = document.createElement("option");
2374 option.value = "MUSHRA";
2375 option.textContent = "MUSHRA";
2376 select.appendChild(option);
2377 select.value = specificationNode.interfaceType;
2378 select.onchange = function(event)
2379 {
2380 specificationNode.interfaceType = event.currentTarget.value;
2381 };
2382 var span = document.createElement("span");
2383 span.textContent = "Interface Type";
2384 div.appendChild(span);
2385 div.appendChild(select);
2386 // Project Return Attribute
2387 span = document.createElement("span");
2388 span.style.margin = "5px";
2389 span.textContent = "Project Return";
2390 var input = document.createElement("input");
2391 input.value = specificationNode.projectReturn;
2392 input.id = "projectReturn";
2393 input.style.margin = "5px";
2394 input.onchange = function(event) {
2395 specificationNode.projectReturn = event.currentTarget.value;
2396 };
2397 div.appendChild(span);
2398 div.appendChild(input);
2399 // Randomise Order
2400 span = document.createElement("span");
2401 span.textContent = "Randomise Order";
2402 input = document.createElement("input");
2403 input.id = "randomiseOrder";
2404 input.style.margin = "5px";
2405 input.type = "checkbox";
2406 input.checked = specificationNode.randomiseOrder;
2407 input.onchange = function(event) {
2408 specificationNode.randomiseOrder = event.currentTarget.checked;
2409 };
2410 div.appendChild(span);
2411 div.appendChild(input);
2412 setupNode.appendChild(div);
2413
2414 // Now create the common Interface Node
2415 var commonInterface = document.createElement("div");
2416 commonInterface.id = "interface";
2417 commonInterface.className = "SecondLevel";
2418 var title = document.createElement("h3");
2419 title.textContent = "Common Interface";
2420 commonInterface.appendChild(title);
2421 var div = document.createElement("div");
2422 div.name = "attributes";
2423 var interfaceOptions;
2424 var interfaceChecks;
2425 switch(select.value)
2426 {
2427 case "APE":
2428 interfaceOptions = APEInterfaceOptions;
2429 interfaceChecks = APEInterfaceChecks;
2430 break;
2431 case "MUSHRA":
2432 interfaceOptions = MUSHRAInterfaceOptions;
2433 interfaceChecks = MUSHRAInterfaceChecks;
2434 break;
2435 }
2436 for (var i=0; i<interfaceOptions[0].length; i++)
2437 {
2438 var span = document.createElement("span");
2439 span.textContent = interfaceOptions[1][i];
2440 var input = document.createElement("input");
2441 input.type = "checkbox";
2442 input.id = interfaceOptions[0][i];
2443 input.setAttribute("name", "option");
2444 div.appendChild(input);
2445 div.appendChild(span);
2446 commonInterface.appendChild(div);
2447 for (var j=0; j<specificationNode.commonInterface.options.length; j++)
2448 {
2449 if (specificationNode.commonInterface.options[j].name == interfaceOptions[0][i])
2450 {
2451 input.checked = true;
2452 break;
2453 }
2454 }
2455 input.onchange = function(event) {
2456 var id = event.currentTarget.id;
2457 if (event.currentTarget.checked) {
2458 specificationNode.commonInterface.options.push(new specificationNode.commonInterface.optionNode(event.currentTarget));
2459 } else {
2460 for (var j=0; j<specificationNode.commonInterface.options.length; j++)
2461 {
2462 if (specificationNode.commonInterface.options[j].name == event.currentTarget.id)
2463 {
2464 specificationNode.commonInterface.options.splice(j,1);
2465 break;
2466 }
2467 }
2468 }
2469 };
2470 }
2471 for (var i=0; i<interfaceChecks[0].length; i++)
2472 {
2473 var span = document.createElement("span");
2474 span.textContent = interfaceChecks[1][i];
2475 var input = document.createElement("input");
2476 input.type = "checkbox";
2477 input.id = interfaceChecks[0][i];
2478 input.setAttribute("name", "check");
2479 div.appendChild(input);
2480 div.appendChild(span);
2481 commonInterface.appendChild(div);
2482 for (var j=0; j<specificationNode.commonInterface.options.length; j++)
2483 {
2484 if (specificationNode.commonInterface.options[j].check == interfaceChecks[0][i])
2485 {
2486 input.checked = true;
2487 break;
2488 }
2489 }
2490 input.onchange = function(event) {
2491 var id = event.currentTarget.id;
2492 if (event.currentTarget.checked) {
2493 specificationNode.commonInterface.options.push(new specificationNode.commonInterface.optionNode(event.currentTarget));
2494 } else {
2495 for (var j=0; j<specificationNode.commonInterface.options.length; j++)
2496 {
2497 if (specificationNode.commonInterface.options[j].name == event.currentTarget.id)
2498 {
2499 specificationNode.commonInterface.options.splice(j,1);
2500 break;
2501 }
2502 }
2503 }
2504 };
2505 }
2506 setupNode.appendChild(commonInterface);
2507 // Now the Metric Node
2508 var metrics = document.createElement("div");
2509 metrics.id = "metrics";
2510 metrics.className = "SecondLevel";
2511 var title = document.createElement("h3");
2512 title.textContent = "Metric Collections";
2513 metrics.appendChild(title);
2514 var div = document.createElement("div");
2515 div.name = "attributes";
2516 metrics.appendChild(div);
2517 var supportedMetrics;
2518 switch(select.value)
2519 {
2520 case "APE":
2521 supportedMetrics = APEInterfaceMetrics;
2522 break;
2523 case "MUSHRA":
2524 supportedMetrics = MUSHRAInterfaceMetrics;
2525 break;
2526 }
2527
2528 for (var i=0; i<supportedMetrics[0].length; i++)
2529 {
2530 var span = document.createElement("span");
2531 span.textContent = supportedMetrics[1][i];
2532 var input = document.createElement("input");
2533 input.type = "checkbox";
2534 input.id = supportedMetrics[0][i];
2535 div.appendChild(input);
2536 div.appendChild(span);
2537 for (var j=0; j<specificationNode.metrics.length; j++)
2538 {
2539 if (specificationNode.metrics[j].enabled == supportedMetrics[0][i])
2540 {
2541 input.checked = true;
2542 }
2543 }
2544 input.onchange = function(event)
2545 {
2546 if (event.currentTarget.checked) {
2547 specificationNode.metrics.push(new specificationNode.metricNode(event.currentTarget.id));
2548 } else {
2549 for (var j=0; j<specificationNode.metrics.length; j++)
2550 {
2551 if (specificationNode.metrics[j].enabled == event.currentTarget.id)
2552 {
2553 specificationNode.metrics.splice(j,1);
2554 break;
2555 }
2556 }
2557 }
2558 };
2559 }
2560
2561 setupNode.appendChild(metrics);
2562
2563 // Test Session Pre Test
2564 var preTest = document.createElement("div");
2565 preTest.id = "preTest";
2566 preTest.className = "SecondLevel";
2567 var title = document.createElement("h3");
2568 title.textContent = "Pre test Survey";
2569 preTest.appendChild(title);
2570 var div = document.createElement("div");
2571 div.name = "attributes";
2572 for (var j=0; j<specificationNode.preTest.options.length; j++)
2573 {
2574 var node = PPSurveyToHTML(specificationNode.preTest.options[j]);
2575 node.className = "SecondLevel";
2576 node.id = preTest.id+"-"+j;
2577 var del_button = document.createElement("button");
2578 del_button.textContent = "Delete";
2579 del_button.onclick = function(event) {
2580 var node = event.currentTarget.parentElement;
2581 var id = node.id.split("-")[1];
2582 specificationNode.preTest.options.splice(id,1);
2583 node.parentElement.removeChild(node);
2584 };
2585 node.appendChild(del_button);
2586 preTest.appendChild(node);
2587 }
2588 setupNode.appendChild(preTest);
2589
2590 // Test Session Post Test
2591 var postTest = document.createElement("div");
2592 postTest.id = "postTest";
2593 postTest.className = "SecondLevel";
2594 var title = document.createElement("h3");
2595 title.textContent = "Post test Survey";
2596 postTest.appendChild(title);
2597 var div = document.createElement("div");
2598 div.name = "attributes";
2599
2600 for (var j=0; j<specificationNode.postTest.options.length; j++)
2601 {
2602 var node = PPSurveyToHTML(specificationNode.postTest.options[j]);
2603 node.className = "SecondLevel";
2604 node.id = postTest.id+"-"+j;
2605 var del_button = document.createElement("button");
2606 del_button.textContent = "Delete";
2607 del_button.onclick = function(event) {
2608 var node = event.currentTarget.parentElement;
2609 var id = node.id.split("-")[1];
2610 specificationNode.postTest.options.splice(id,1);
2611 node.parentElement.removeChild(node);
2612 };
2613 node.appendChild(del_button);
2614 postTest.appendChild(node);
2615 }
2616
2617 setupNode.appendChild(postTest);
2618
2619 destination.appendChild(setupNode);
2620
2621 // Now we step through the AudioHolders
2622 for (var i=0; i<specificationNode.audioHolders.length; i++)
2623 {
2624 var aH = specificationNode.audioHolders[i];
2625 var aHTML = document.createElement("div");
2626 aHTML.name = "audioHolder";
2627 aHTML.id = "audioHolder-"+i;
2628 aHTML.className = "topLevel";
2629 aHTML.appendChild(createDeleteNodeButton());
2630 destination.appendChild(aHTML);
2631 var title = document.createElement("h2");
2632 title.textContent = "Audio Holder "+aH.id;
2633 aHTML.appendChild(title);
2634 var attributes = document.createElement("div");
2635 attributes.name = "attributes";
2636 aHTML.appendChild(attributes);
2637 var text = document.createElement("span");
2638 text.textContent = "ID: ";
2639 var input = document.createElement("input");
2640 input.id = aHTML.id+"-id";
2641 input.value = aH.id;
2642 input.onchange = function()
2643 {
2644 var IDSplit = event.currentTarget.id.split('-');
2645 var aholderID = IDSplit[0]+"-"+IDSplit[1];
2646 var aholder = document.getElementById(aholderID);
2647 title = aholder.getElementsByTagName("h2")[0];
2648 title.textContent = "Audio Holder "+event.currentTarget.value;
2649 specificationNode.audioHolders[IDSplit[1]].id = event.currentTarget.value;
2650 };
2651 text.style.margin = "5px";
2652 input.style.margin = "5px";
2653 attributes.appendChild(text);
2654 attributes.appendChild(input);
2655 text = document.createElement("span");
2656 text.textContent = "Host URL: ";
2657 input = document.createElement("input");
2658 input.id = aHTML.id+"-hostURL";
2659 input.value = aH.hostURL;
2660 input.onchange = function()
2661 {
2662 var IDSplit = event.currentTarget.id.split('-');
2663 specificationNode.audioHolders[IDSplit[1]].hostURL = event.currentTarget.value;
2664 };
2665 text.style.margin = "5px";
2666 input.style.margin = "5px";
2667 attributes.appendChild(text);
2668 attributes.appendChild(input);
2669 text = document.createElement("span");
2670 text.textContent = "Loop Fragments: ";
2671 input = document.createElement("input");
2672 input.id = aHTML.id+"-loop";
2673 input.type = "checkbox";
2674 input.checked = aH.loop;
2675 input.onchange = function()
2676 {
2677 var IDSplit = event.currentTarget.id.split('-');
2678 specificationNode.audioHolders[IDSplit[1]].loop = event.currentTarget.checked;
2679 };
2680 text.style.margin = "5px";
2681 input.style.margin = "5px";
2682 attributes.appendChild(text);
2683 attributes.appendChild(input);
2684 text = document.createElement("span");
2685 text.textContent = "Randomise Order: ";
2686 input = document.createElement("input");
2687 input.id = aHTML.id+"-randomiseOrder";
2688 input.type = "checkbox";
2689 input.checked = aH.randomiseOrder;
2690 input.onchange = function()
2691 {
2692 var IDSplit = event.currentTarget.id.split('-');
2693 specificationNode.audioHolders[IDSplit[1]].randomiseOrder = event.currentTarget.checked;
2694 };
2695 text.style.margin = "5px";
2696 input.style.margin = "5px";
2697 attributes.appendChild(text);
2698 attributes.appendChild(input);
2699 text = document.createElement("span");
2700 text.textContent = "Show Fragment Comments";
2701 input = document.createElement("input");
2702 input.id = aHTML.id+"-elementComments";
2703 input.type = "checkbox";
2704 input.checked = aH.elementComments;
2705 input.onchange = function()
2706 {
2707 var IDSplit = event.currentTarget.id.split('-');
2708 specificationNode.audioHolders[IDSplit[1]].elementComments = event.currentTarget.checked;
2709 };
2710 text.style.margin = "5px";
2711 input.style.margin = "5px";
2712 attributes.appendChild(text);
2713 attributes.appendChild(input);
2714
2715 // Test Session Pre Test
2716 var preTest = document.createElement("div");
2717 preTest.id = aHTML.id+"-pretest";
2718 preTest.className = "SecondLevel";
2719 var title = document.createElement("h3");
2720 title.textContent = "Pre test Survey";
2721 preTest.appendChild(title);
2722 var div = document.createElement("div");
2723 div.name = "attributes";
2724
2725 for (var j=0; j<aH.preTest.options.length; j++)
2726 {
2727 var node = PPSurveyToHTML(aH.preTest.options[j]);
2728 node.className = "SecondLevel";
2729 node.id = preTest.id+"-"+j;
2730 var button_delete = document.createElement("button");
2731 button_delete.textContent = "Delete";
2732 button_delete.onclick = function(event)
2733 {
2734 var node = event.currentTarget.parentElement;
2735 var IDSplit = node.id.split("-");
2736 var preTest = specificationNode.audioHolders[IDSplit[1]].preTest;
2737 preTest.options.splice(IDSplit[3],1);
2738 node.parentElement.removeChild(node);
2739 };
2740 node.appendChild(button_delete);
2741 preTest.appendChild(node);
2742 }
2743
2744 aHTML.appendChild(preTest);
2745
2746 // Test Session Post Test
2747 var postTest = document.createElement("div");
2748 postTest.id = aHTML.id+"-postTest";
2749 postTest.className = "SecondLevel";
2750 var title = document.createElement("h3");
2751 title.textContent = "Post test Survey";
2752 postTest.appendChild(title);
2753 var div = document.createElement("div");
2754 div.name = "attributes";
2755
2756 for (var j=0; j<aH.postTest.options.length; j++)
2757 {
2758 var node = PPSurveyToHTML(aH.postTest.options[j]);
2759 node.className = "SecondLevel";
2760 node.id = postTest.id+"-"+j;
2761 var button_delete = document.createElement("button");
2762 button_delete.textContent = "Delete";
2763 button_delete.onclick = function(event)
2764 {
2765 var node = event.currentTarget.parentElement;
2766 var IDSplit = node.id.split("-");
2767 var postTest = specificationNode.audioHolders[IDSplit[1]].postTest;
2768 postTest.options.splice(IDSplit[3],1);
2769 node.parentElement.removeChild(node);
2770 };
2771 node.appendChild(button_delete);
2772 postTest.appendChild(node);
2773 }
2774
2775 aHTML.appendChild(postTest);
2776
2777 //Audio Elements
2778 var audioElems = document.createElement("div");
2779 audioElems.id = aHTML.id+"-audioElements";
2780 audioElems.className = "SecondLevel";
2781 var title = document.createElement("h3");
2782 title.textContent = "Audio Elements";
2783 audioElems.appendChild(title);
2784 for (var j=0; j<aH.audioElements.length; j++)
2785 {
2786 var entry = document.createElement("div");
2787 entry.className = "SecondLevel";
2788 entry.id = audioElems.id+"-"+aH.audioElements[j].id;
2789 var text = document.createElement("span");
2790 text.textContent = "ID:";
2791 var input = document.createElement("input");
2792 input.id = entry.id+"-id";
2793 input.value = aH.audioElements[j].id;
2794 input.onchange = function() {
2795 var IDSplit = event.currentTarget.id.split("-");
2796 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2797 ahNode.audioElements[IDSplit[3]].id = event.currentTarget.value;
2798 };
2799 text.style.margin = "5px";
2800 input.style.margin = "5px";
2801 entry.appendChild(text);
2802 entry.appendChild(input);
2803 text = document.createElement("span");
2804 text.textContent = "URL:";
2805 input = document.createElement("input");
2806 input.id = entry.id+"-URL";
2807 input.value = aH.audioElements[j].url;
2808 input.onchange = function() {
2809 var IDSplit = event.currentTarget.id.split("-");
2810 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2811 ahNode.audioElements[IDSplit[3]].url = event.currentTarget.value;
2812 };
2813 text.style.margin = "5px";
2814 input.style.margin = "5px";
2815 entry.appendChild(text);
2816 entry.appendChild(input);
2817 text = document.createElement("span");
2818 text.textContent = "Gain:";
2819 input = document.createElement("input");
2820 input.type = "range";
2821 input.id = entry.id+"-gain";
2822 input.value = aH.audioElements[j].gain;
2823 input.min = -25;
2824 input.max = 6;
2825 input.step = 1;
2826 input.onchange = function() {
2827 var IDSplit = event.currentTarget.id.split("-");
2828 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2829 ahNode.audioElements[IDSplit[3]].gain = decibelToLinear(Number(event.currentTarget.value));
2830 var textRet = document.getElementById(event.currentTarget.id+"-ret");
2831 textRet.textContent = String(event.currentTarget.value)+"dB";
2832 };
2833 var textRet = document.createElement("span");
2834 textRet.textContent = String(linearToDecibel(aH.audioElements[j].gain))+"dB";
2835 textRet.id = entry.id+"-gain-ret";
2836 text.style.margin = "5px";
2837 input.style.margin = "5px";
2838 entry.appendChild(text);
2839 entry.appendChild(input);
2840 entry.appendChild(textRet);
2841 var button_delete = document.createElement("button");
2842 button_delete.textContent = "Delete";
2843 button_delete.onclick = function() {
2844 var node = event.currentTarget.parentElement;
2845 var IDSplit = node.id.split("-");
2846 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2847 ahNode.audioElements.splice(IDSplit[3],1);
2848 node.parentElement.removeChild(node);
2849 };
2850 entry.appendChild(button_delete);
2851 audioElems.appendChild(entry);
2852 }
2853 aHTML.appendChild(audioElems);
2854 }
2855
2856 function PPSurveyToHTML(node)
2857 {
2858 var holder = document.createElement("div");
2859 var title = document.createElement("h4");
2860 holder.appendChild(title);
2861 var attributes = document.createElement("div");
2862 holder.appendChild(attributes);
2863 switch(node.type)
2864 {
2865 case "statement":
2866 title.textContent = "Statement";
2867 var tA = document.createElement("textarea");
2868 attributes.style.height = "150px";
2869 tA.style.width = "500px";
2870 tA.style.height = "100px";
2871 tA.value = node.statement;
2872 attributes.appendChild(tA);
2873 break;
2874 case "question":
2875 title.textContent = "Question";
2876 var text = document.createElement("span");
2877 text.textContent = "ID :";
2878 var input = document.createElement("input");
2879 input.name = "id";
2880 input.value = node.id;
2881 text.style.margin = "5px";
2882 input.style.margin = "5px";
2883 attributes.appendChild(text);
2884 attributes.appendChild(input);
2885 text = document.createElement("span");
2886 text.textContent = "Question";
2887 input = document.createElement("input");
2888 input.name = "question";
2889 input.style.width = "400px";
2890 input.value = node.question;
2891 text.style.margin = "5px";
2892 input.style.margin = "5px";
2893 attributes.appendChild(text);
2894 attributes.appendChild(input);
2895 text = document.createElement("span");
2896 text.textContent = "Mandatory";
2897 input = document.createElement("input");
2898 input.name = "mandatory";
2899 input.type = "checkbox";
2900 input.checked = node.mandatory;
2901 text.style.margin = "5px";
2902 input.style.margin = "5px";
2903 attributes.appendChild(text);
2904 attributes.appendChild(input);
2905 text = document.createElement("span");
2906 text.textContent = "Reply box size";
2907 input = document.createElement("select");
2908 input.name = "boxsize";
2909 var option = document.createElement("option");
2910 option.textContent = "Normal";
2911 option.value = "normal";
2912 input.appendChild(option);
2913 option = document.createElement("option");
2914 option.textContent = "Large";
2915 option.value = "large";
2916 input.appendChild(option);
2917 option = document.createElement("option");
2918 option.textContent = "Small";
2919 option.value = "small";
2920 input.appendChild(option);
2921 option = document.createElement("option");
2922 option.textContent = "Huge";
2923 option.value = "huge";
2924 input.appendChild(option);
2925 text.style.margin = "5px";
2926 input.style.margin = "5px";
2927 attributes.appendChild(text);
2928 attributes.appendChild(input);
2929 input.value = node.boxsize;
2930 break;
2931 }
2932 return holder;
2933 }
2934 }
2935 function exportToXML()
2936 {
2937 var xmlDoc = specificationNode.encode();
2938 var oSerializer = new XMLSerializer();
2939 xmlDoc = oSerializer.serializeToString(xmlDoc);
2940 var parent = document.createElement("div");
2941 var file = [xmlDoc];
2942 var bb = new Blob(file,{type : 'application/xml'});
2943 var dnlk = window.URL.createObjectURL(bb);
2944 var a = document.createElement("a");
2945 a.hidden = '';
2946 a.href = dnlk;
2947 a.download = "save.xml";
2948 a.textContent = "Save File";
2949
2950 popupInstance.showPopup();
2951 popupInstance.popupBody.innerHTML = null;
2952 var body = document.createElement("span");
2953 body.textContent = "Right click and save the file using the link below. Place this file in your WAET directory as 'project.xml' in the example_eval/ directory. Place your media files in the location specified by the Host URL entries. If you wish to review this XML or edit it, refresh this tool and drag your XML document into the page on the welcome screen.";
2954 popupInstance.popupBody.appendChild(body);
2955 popupInstance.popupBody.appendChild(a);
2956 popupInstance.popupTitle.innerHTML = "<span>Thank You</span>";
2957 }
2958 </script>
2959 <style>
2960 div.popup {
2961 width: 500px;
2962 position: absolute;
2963 height: 400px;
2964 background-color: #fff;
2965 border-radius: 10px;
2966 box-shadow: 0px 0px 50px #000;
2967 z-index: 2;
2968 }
2969
2970 button.popupButton {
2971 /* Button for popup window
2972 */
2973 min-width: 50px;
2974 height: 25px;
2975 position: relative;
2976 border-radius: 5px;
2977 border: #444;
2978 border-width: 1px;
2979 border-style: solid;
2980 background-color: #fff;
2981 }
2982
2983 div.dragndrop {
2984 margin-top: 10px;
2985 border:#000000;
2986 border-style: dashed;
2987 border-width: 2px;
2988 }
2989 div.dndheaderelement {
2990 float: left;
2991 height: 100%;
2992 border-right: #DDDDDD;
2993 border-right-width: 1px;
2994 border-right-style: solid;
2995 }
2996 div.dndheaderelement span{
2997 padding-left: 5px;
2998 }
2999
3000 div.topLevel {
3001 border: #000;
3002 border-style: solid;
3003 border-width: 5px;
3004 padding: 10px;
3005 margin: 10px;
3006 }
3007
3008 div.SecondLevel {
3009 border: #000;
3010 border-style: solid;
3011 border-width: 1px;
3012 padding: 10px;
3013 margin: 10px;
3014 }
3015 </style>
3016 </head>
3017
3018 <body>
3019 <div id="export">
3020 <button id="exportToXML" onclick="exportToXML();">Export XML</button>
3021 </div>
3022 <div id="content"></div>
3023 </body>
3024 </html> 601 </html>