Mercurial > hg > webaudioevaluationtool
comparison interfaces/AB.js @ 1088:3705f68a38b7
The version I use and works, addresses issues #1622, #1616, partially #1620
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 22 Feb 2016 04:17:19 +0000 |
parents | |
children | b5bf2f57187c a4ad9e55b5b8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 1088:3705f68a38b7 |
---|---|
1 // Once this is loaded and parsed, begin execution | |
2 loadInterface(); | |
3 | |
4 function loadInterface() { | |
5 // Get the dimensions of the screen available to the page | |
6 var width = window.innerWidth; | |
7 var height = window.innerHeight; | |
8 interfaceContext.insertPoint.innerHTML = null; // Clear the current schema | |
9 | |
10 // Custom Comparitor Object | |
11 Interface.prototype.comparitor = null; | |
12 | |
13 // The injection point into the HTML page | |
14 interfaceContext.insertPoint = document.getElementById("topLevelBody"); | |
15 var testContent = document.createElement('div'); | |
16 testContent.id = 'testContent'; | |
17 | |
18 // Create the top div for the Title element | |
19 var titleAttr = specification.title; | |
20 var title = document.createElement('div'); | |
21 title.className = "title"; | |
22 title.align = "center"; | |
23 var titleSpan = document.createElement('span'); | |
24 | |
25 // Set title to that defined in XML, else set to default | |
26 if (titleAttr != undefined) { | |
27 titleSpan.textContent = titleAttr; | |
28 } else { | |
29 titleSpan.textContent = 'Listening test'; | |
30 } | |
31 // Insert the titleSpan element into the title div element. | |
32 title.appendChild(titleSpan); | |
33 | |
34 var pagetitle = document.createElement('div'); | |
35 pagetitle.className = "pageTitle"; | |
36 pagetitle.align = "center"; | |
37 var titleSpan = document.createElement('span'); | |
38 titleSpan.id = "pageTitle"; | |
39 pagetitle.appendChild(titleSpan); | |
40 | |
41 // Create Interface buttons! | |
42 var interfaceButtons = document.createElement('div'); | |
43 interfaceButtons.id = 'interface-buttons'; | |
44 interfaceButtons.style.height = '25px'; | |
45 | |
46 // Create playback start/stop points | |
47 var playback = document.createElement("button"); | |
48 playback.innerHTML = 'Stop'; | |
49 playback.id = 'playback-button'; | |
50 playback.style.float = 'left'; | |
51 // onclick function. Check if it is playing or not, call the correct function in the | |
52 // audioEngine, change the button text to reflect the next state. | |
53 playback.onclick = function() { | |
54 if (audioEngineContext.status == 1) { | |
55 audioEngineContext.stop(); | |
56 this.innerHTML = 'Stop'; | |
57 var time = audioEngineContext.timer.getTestTime(); | |
58 console.log('Stopped at ' + time); // DEBUG/SAFETY | |
59 } | |
60 }; | |
61 // Append the interface buttons into the interfaceButtons object. | |
62 interfaceButtons.appendChild(playback); | |
63 | |
64 // Global parent for the comment boxes on the page | |
65 var feedbackHolder = document.createElement('div'); | |
66 feedbackHolder.id = 'feedbackHolder'; | |
67 | |
68 // Construct the AB Boxes | |
69 var boxes = document.createElement('div'); | |
70 boxes.align = "center"; | |
71 boxes.id = "box-holders"; | |
72 boxes.style.float = "left"; | |
73 | |
74 var submit = document.createElement('button'); | |
75 submit.id = "submit"; | |
76 submit.onclick = buttonSubmitClick; | |
77 submit.className = "big-button"; | |
78 submit.textContent = "submit"; | |
79 submit.style.position = "relative"; | |
80 submit.style.left = (window.innerWidth-250)/2 + 'px'; | |
81 | |
82 feedbackHolder.appendChild(boxes); | |
83 | |
84 // Inject into HTML | |
85 testContent.appendChild(title); // Insert the title | |
86 testContent.appendChild(pagetitle); | |
87 testContent.appendChild(interfaceButtons); | |
88 testContent.appendChild(feedbackHolder); | |
89 testContent.appendChild(submit); | |
90 interfaceContext.insertPoint.appendChild(testContent); | |
91 | |
92 // Load the full interface | |
93 testState.initialise(); | |
94 testState.advanceState(); | |
95 } | |
96 | |
97 function loadTest(audioHolderObject) | |
98 { | |
99 var feedbackHolder = document.getElementById('feedbackHolder'); | |
100 var interfaceObj = audioHolderObject.interfaces; | |
101 if (interfaceObj.length > 1) | |
102 { | |
103 console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); | |
104 } | |
105 interfaceObj = interfaceObj[0]; | |
106 | |
107 if(interfaceObj.title != null) | |
108 { | |
109 document.getElementById("pageTitle").textContent = interfaceObj.title; | |
110 } | |
111 | |
112 var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); | |
113 for (var option of interfaceOptions) | |
114 { | |
115 if (option.type == "show") | |
116 { | |
117 switch(option.name) { | |
118 case "playhead": | |
119 var playbackHolder = document.getElementById('playback-holder'); | |
120 if (playbackHolder == null) | |
121 { | |
122 playbackHolder = document.createElement('div'); | |
123 playbackHolder.style.width = "100%"; | |
124 playbackHolder.style.float = "left"; | |
125 playbackHolder.align = 'center'; | |
126 playbackHolder.appendChild(interfaceContext.playhead.object); | |
127 feedbackHolder.appendChild(playbackHolder); | |
128 } | |
129 break; | |
130 case "page-count": | |
131 var pagecountHolder = document.getElementById('page-count'); | |
132 if (pagecountHolder == null) | |
133 { | |
134 pagecountHolder = document.createElement('div'); | |
135 pagecountHolder.id = 'page-count'; | |
136 } | |
137 pagecountHolder.innerHTML = '<span>Page '+(audioHolderObject.presentedId+1)+' of '+specification.pages.length+'</span>'; | |
138 var inject = document.getElementById('interface-buttons'); | |
139 inject.appendChild(pagecountHolder); | |
140 break; | |
141 case "volume": | |
142 if (document.getElementById('master-volume-holder') == null) | |
143 { | |
144 feedbackHolder.appendChild(interfaceContext.volume.object); | |
145 } | |
146 break; | |
147 } | |
148 } | |
149 } | |
150 | |
151 // Populate the comparitor object | |
152 interfaceContext.comparitor = new Comparitor(audioHolderObject); | |
153 if (audioHolderObject.showElementComments) | |
154 { | |
155 var commentHolder = document.createElement('div'); | |
156 commentHolder.id = 'commentHolder'; | |
157 document.getElementById('testContent').appendChild(commentHolder); | |
158 // Generate one comment box per presented page | |
159 for (var element of audioEngineContext.audioObjects) | |
160 { | |
161 interfaceContext.createCommentBox(element); | |
162 } | |
163 interfaceContext.showCommentBoxes(commentHolder,true); | |
164 } | |
165 resizeWindow(null); | |
166 } | |
167 | |
168 function Comparitor(audioHolderObject) | |
169 { | |
170 this.comparitorBox = function(audioElement,id,text) | |
171 { | |
172 this.parent = audioElement; | |
173 this.id = id; | |
174 this.value = 0; | |
175 this.disabled = true; | |
176 this.box = document.createElement('div'); | |
177 this.box.className = 'comparitor-holder'; | |
178 this.box.setAttribute('track-id',audioElement.id); | |
179 this.box.id = 'comparitor-'+text; | |
180 this.selector = document.createElement('div'); | |
181 this.selector.className = 'comparitor-selector disabled'; | |
182 var selectorText = document.createElement('span'); | |
183 selectorText.textContent = text; | |
184 this.selector.appendChild(selectorText); | |
185 this.playback = document.createElement('button'); | |
186 this.playback.className = 'comparitor-button'; | |
187 this.playback.disabled = true; | |
188 this.playback.textContent = "Listen"; | |
189 this.box.appendChild(this.selector); | |
190 this.box.appendChild(this.playback); | |
191 this.selector.onclick = function(event) | |
192 { | |
193 var time = audioEngineContext.timer.getTestTime(); | |
194 if ($(event.currentTarget).hasClass('disabled')) | |
195 { | |
196 console.log("Please wait until sample has loaded"); | |
197 return; | |
198 } | |
199 if (audioEngineContext.status == 0) | |
200 { | |
201 alert("Please listen to the samples before making a selection"); | |
202 console.log("Please listen to the samples before making a selection"); | |
203 return; | |
204 } | |
205 $(".comparitor-selector").removeClass('selected'); | |
206 var id = event.currentTarget.parentElement.getAttribute('track-id'); | |
207 interfaceContext.comparitor.selected = id; | |
208 $(event.currentTarget).addClass('selected'); | |
209 for (var i=0; i<interfaceContext.comparitor.comparitors.length; i++) | |
210 { | |
211 var obj = interfaceContext.comparitor.comparitors[i]; | |
212 if (i == id) { | |
213 obj.value = 1; | |
214 } else { | |
215 obj.value = 0; | |
216 } | |
217 obj.parent.metric.moved(time,obj.value); | |
218 } | |
219 console.log("Selected "+id+' ('+time+')'); | |
220 }; | |
221 this.playback.setAttribute("playstate","ready"); | |
222 this.playback.onclick = function(event) | |
223 { | |
224 var id = event.currentTarget.parentElement.getAttribute('track-id'); | |
225 if (event.currentTarget.getAttribute("playstate") == "ready") | |
226 { | |
227 audioEngineContext.play(id); | |
228 } else if (event.currentTarget.getAttribute("playstate") == "playing") { | |
229 audioEngineContext.stop(); | |
230 } | |
231 | |
232 }; | |
233 | |
234 this.enable = function() | |
235 { | |
236 if (this.parent.state == 1) | |
237 { | |
238 $(this.selector).removeClass('disabled'); | |
239 this.playback.disabled = false; | |
240 } | |
241 }; | |
242 this.updateLoading = function(progress) | |
243 { | |
244 if (progress != 100) | |
245 { | |
246 progress = String(progress); | |
247 progress = progress.split('.')[0]; | |
248 this.playback.textContent = progress+'%'; | |
249 } else { | |
250 this.playback.textContent = "Play"; | |
251 } | |
252 }; | |
253 this.startPlayback = function() | |
254 { | |
255 $('.comparitor-button').text('Listen'); | |
256 $(this.playback).text('Stop'); | |
257 this.playback.setAttribute("playstate","playing"); | |
258 }; | |
259 this.stopPlayback = function() | |
260 { | |
261 $(this.playback).text('Listen'); | |
262 this.playback.setAttribute("playstate","ready"); | |
263 }; | |
264 this.exportXMLDOM = function(audioObject) | |
265 { | |
266 var node = storage.document.createElement('value'); | |
267 node.textContent = this.value; | |
268 return node; | |
269 }; | |
270 this.getValue = function() { | |
271 return this.value; | |
272 }; | |
273 this.getPresentedId = function() | |
274 { | |
275 return this.selector.children[0].textContent; | |
276 }; | |
277 this.canMove = function() | |
278 { | |
279 return false; | |
280 }; | |
281 }; | |
282 | |
283 this.boxHolders = document.getElementById('box-holders'); | |
284 this.boxHolders.innerHTML = null; | |
285 this.comparitors = []; | |
286 this.selected = null; | |
287 | |
288 // First generate the Audio Objects for the Audio Engine | |
289 for (var index=0; index<audioHolderObject.audioElements.length; index++) | |
290 { | |
291 var element = audioHolderObject.audioElements[index]; | |
292 if (index == audioHolderObject.outsideReference || element.type == 'outside-reference') | |
293 { | |
294 console.log("WARNING - AB cannot have fixed reference"); | |
295 } | |
296 var audioObject = audioEngineContext.newTrack(element); | |
297 var node = new this.comparitorBox(audioObject,index,String.fromCharCode(65 + index)); | |
298 audioObject.bindInterface(node); | |
299 this.comparitors.push(node); | |
300 this.boxHolders.appendChild(node.box); | |
301 } | |
302 return this; | |
303 } | |
304 | |
305 function resizeWindow(event) | |
306 { | |
307 document.getElementById('submit').style.left = (window.innerWidth-250)/2 + 'px'; | |
308 var numObj = interfaceContext.comparitor.comparitors.length; | |
309 var boxW = numObj*312; | |
310 var diff = window.innerWidth - boxW; | |
311 while (diff < 0) | |
312 { | |
313 numObj = Math.ceil(numObj/2); | |
314 boxW = numObj*312; | |
315 diff = window.innerWidth - boxW; | |
316 } | |
317 document.getElementById('box-holders').style.marginLeft = diff/2 + 'px'; | |
318 document.getElementById('box-holders').style.marginRight = diff/2 + 'px'; | |
319 document.getElementById('box-holders').style.width = boxW + 'px'; | |
320 } | |
321 | |
322 function buttonSubmitClick() | |
323 { | |
324 var checks = []; | |
325 checks = checks.concat(testState.currentStateMap.interfaces[0].options); | |
326 checks = checks.concat(specification.interfaces.options); | |
327 var canContinue = true; | |
328 | |
329 for (var i=0; i<checks.length; i++) { | |
330 if (checks[i].type == 'check') | |
331 { | |
332 switch(checks[i].name) { | |
333 case 'fragmentPlayed': | |
334 // Check if all fragments have been played | |
335 var checkState = interfaceContext.checkAllPlayed(); | |
336 if (checkState == false) {canContinue = false;} | |
337 break; | |
338 case 'fragmentFullPlayback': | |
339 // Check all fragments have been played to their full length | |
340 var checkState = interfaceContext.checkFragmentsFullyPlayed(); | |
341 if (checkState == false) {canContinue = false;} | |
342 break; | |
343 case 'fragmentMoved': | |
344 // Check all fragment sliders have been moved. | |
345 var checkState = interfaceContext.checkAllMoved(); | |
346 if (checkState == false) {canContinue = false;} | |
347 break; | |
348 case 'fragmentComments': | |
349 // Check all fragment sliders have been moved. | |
350 var checkState = interfaceContext.checkAllCommented(); | |
351 if (checkState == false) {canContinue = false;} | |
352 break; | |
353 default: | |
354 console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); | |
355 break; | |
356 } | |
357 | |
358 } | |
359 if (!canContinue) {break;} | |
360 } | |
361 if (canContinue) | |
362 { | |
363 if (audioEngineContext.status == 1) { | |
364 var playback = document.getElementById('playback-button'); | |
365 playback.click(); | |
366 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options | |
367 } else | |
368 { | |
369 if (audioEngineContext.timer.testStarted == false) | |
370 { | |
371 alert('You have not started the test! Please press start to begin the test!'); | |
372 return; | |
373 } | |
374 } | |
375 testState.advanceState(); | |
376 } | |
377 } | |
378 | |
379 function pageXMLSave(store, pageSpecification) | |
380 { | |
381 // MANDATORY | |
382 // Saves a specific test page | |
383 // You can use this space to add any extra nodes to your XML <audioHolder> saves | |
384 // Get the current <page> information in store (remember to appendChild your data to it) | |
385 // pageSpecification is the current page node configuration | |
386 // To create new XML nodes, use storage.document.createElement(); | |
387 } |