Mercurial > hg > webaudioevaluationtool
comparison ape.js @ 656:0a401224660b
Added dev-main branch warning at top of files
author | Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk> |
---|---|
date | Fri, 10 Apr 2015 10:25:52 +0100 |
parents | |
children | 1e64848f5940 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 656:0a401224660b |
---|---|
1 /** | |
2 * ape.js | |
3 * Create the APE interface | |
4 */ | |
5 | |
6 /* | |
7 * | |
8 * WARNING!!! | |
9 * | |
10 * YOU ARE VIEWING THE DEV VERSION. THERE IS NO GUARANTEE THIS WILL BE FULLY FUNCTIONAL | |
11 * | |
12 * WARNING!!! | |
13 * | |
14 */ | |
15 | |
16 | |
17 // Once this is loaded and parsed, begin execution | |
18 loadInterface(projectXML); | |
19 | |
20 function loadInterface(xmlDoc) { | |
21 | |
22 // Get the dimensions of the screen available to the page | |
23 var width = window.innerWidth; | |
24 var height = window.innerHeight; | |
25 | |
26 // Set background to grey #ddd | |
27 document.getElementsByTagName('body')[0].style.backgroundColor = '#ddd'; | |
28 | |
29 // The injection point into the HTML page | |
30 var insertPoint = document.getElementById("topLevelBody"); | |
31 var testContent = document.createElement('div'); | |
32 testContent.id = 'testContent'; | |
33 | |
34 | |
35 // Decode parts of the xmlDoc that are needed | |
36 // xmlDoc MUST already be parsed by jQuery! | |
37 var xmlSetup = xmlDoc.find('setup'); | |
38 // Should put in an error function here incase of malprocessed or malformed XML | |
39 | |
40 // Create the top div for the Title element | |
41 var titleAttr = xmlSetup[0].attributes['title']; | |
42 var title = document.createElement('div'); | |
43 title.className = "title"; | |
44 title.align = "center"; | |
45 var titleSpan = document.createElement('span'); | |
46 | |
47 // Set title to that defined in XML, else set to default | |
48 if (titleAttr != undefined) { | |
49 titleSpan.innerHTML = titleAttr.value; | |
50 } else { | |
51 titleSpan.innerHTML = 'APE Tool'; | |
52 } | |
53 // Insert the titleSpan element into the title div element. | |
54 title.appendChild(titleSpan); | |
55 | |
56 // Store the return URL path in global projectReturn | |
57 projectReturn = xmlSetup[0].attributes['projectReturn'].value; | |
58 | |
59 // Create Interface buttons! | |
60 var interfaceButtons = document.createElement('div'); | |
61 interfaceButtons.id = 'interface-buttons'; | |
62 | |
63 // MANUAL DOWNLOAD POINT | |
64 // If project return is null, this MUST be specified as the location to create the download link | |
65 var downloadPoint = document.createElement('div'); | |
66 downloadPoint.id = 'download-point'; | |
67 | |
68 // Create playback start/stop points | |
69 var playback = document.createElement("button"); | |
70 playback.innerHTML = 'Start'; | |
71 // onclick function. Check if it is playing or not, call the correct function in the | |
72 // audioEngine, change the button text to reflect the next state. | |
73 playback.onclick = function() { | |
74 if (audioEngineContext.status == 0) { | |
75 audioEngineContext.play(); | |
76 this.innerHTML = 'Stop'; | |
77 } else { | |
78 audioEngineContext.stop(); | |
79 this.innerHTML = 'Start'; | |
80 } | |
81 }; | |
82 // Create Submit (save) button | |
83 var submit = document.createElement("button"); | |
84 submit.innerHTML = 'Submit'; | |
85 submit.onclick = function() { | |
86 // TODO: Update this for postTest tags | |
87 createProjectSave(projectReturn) | |
88 }; | |
89 // Append the interface buttons into the interfaceButtons object. | |
90 interfaceButtons.appendChild(playback); | |
91 interfaceButtons.appendChild(submit); | |
92 interfaceButtons.appendChild(downloadPoint); | |
93 | |
94 // Now create the slider and HTML5 canvas boxes | |
95 | |
96 // Create the div box to center align | |
97 var sliderBox = document.createElement('div'); | |
98 sliderBox.className = 'sliderCanvasDiv'; | |
99 sliderBox.id = 'sliderCanvasHolder'; | |
100 sliderBox.align = 'center'; | |
101 | |
102 // Create the slider box to hold the slider elements | |
103 var canvas = document.createElement('div'); | |
104 canvas.id = 'slider'; | |
105 // Must have a known EXACT width, as this is used later to determine the ratings | |
106 canvas.style.width = width - 100 +"px"; | |
107 canvas.style.height = 150 + "px"; | |
108 canvas.style.marginBottom = "25px"; | |
109 canvas.style.backgroundColor = '#eee'; | |
110 canvas.align = "left"; | |
111 sliderBox.appendChild(canvas); | |
112 | |
113 // Global parent for the comment boxes on the page | |
114 var feedbackHolder = document.createElement('div'); | |
115 // Find the parent audioHolder object. | |
116 var audioHolder = xmlDoc.find('audioHolder'); | |
117 audioHolder = audioHolder[0]; // Remove from one field array | |
118 // Extract the hostURL attribute. If not set, create an empty string. | |
119 var hostURL = audioHolder.attributes['hostURL']; | |
120 if (hostURL == undefined) { | |
121 hostURL = ""; | |
122 } else { | |
123 hostURL = hostURL.value; | |
124 } | |
125 // Extract the sampleRate. If set, convert the string to a Number. | |
126 var hostFs = audioHolder.attributes['sampleRate']; | |
127 if (hostFs != undefined) { | |
128 hostFs = Number(hostFs.value); | |
129 } | |
130 | |
131 /// CHECK FOR SAMPLE RATE COMPATIBILITY | |
132 if (hostFs != undefined) { | |
133 if (Number(hostFs) != audioContext.sampleRate) { | |
134 var errStr = 'Sample rates do not match! Requested '+Number(hostFs)+', got '+audioContext.sampleRate+'. Please set the sample rate to match before completing this test.'; | |
135 alert(errStr); | |
136 return; | |
137 } | |
138 } | |
139 // Find all the audioElements from the audioHolder | |
140 var audioElements = $(audioHolder).find('audioElements'); | |
141 audioElements.each(function(index,element){ | |
142 // Find URL of track | |
143 // In this jQuery loop, variable 'this' holds the current audioElement. | |
144 | |
145 // Now load each audio sample. First create the new track by passing the full URL | |
146 var trackURL = hostURL + this.attributes['url'].value; | |
147 audioEngineContext.newTrack(trackURL); | |
148 // Create document objects to hold the comment boxes | |
149 var trackComment = document.createElement('div'); | |
150 // Create a string next to each comment asking for a comment | |
151 var trackString = document.createElement('span'); | |
152 trackString.innerHTML = 'Comment on track '+index; | |
153 // Create the HTML5 comment box 'textarea' | |
154 var trackCommentBox = document.createElement('textarea'); | |
155 trackCommentBox.rows = '4'; | |
156 trackCommentBox.cols = '100'; | |
157 trackCommentBox.name = 'trackComment'+index; | |
158 trackCommentBox.className = 'trackComment'; | |
159 // Add to the holder. | |
160 trackComment.appendChild(trackString); | |
161 trackComment.appendChild(trackCommentBox); | |
162 feedbackHolder.appendChild(trackComment); | |
163 | |
164 // Create a slider per track | |
165 | |
166 var trackSliderObj = document.createElement('div'); | |
167 trackSliderObj.className = 'track-slider'; | |
168 trackSliderObj.id = 'track-slider-'+index; | |
169 trackSliderObj.style.position = 'absolute'; | |
170 // Distribute it randomnly | |
171 var w = window.innerWidth - 100; | |
172 w = Math.random()*w; | |
173 trackSliderObj.style.left = Math.floor(w)+50+'px'; | |
174 trackSliderObj.style.height = "150px"; | |
175 trackSliderObj.style.width = "10px"; | |
176 trackSliderObj.style.backgroundColor = 'rgb(100,200,100)'; | |
177 trackSliderObj.innerHTML = '<span>'+index+'</span>'; | |
178 trackSliderObj.style.float = "left"; | |
179 trackSliderObj.draggable = true; | |
180 trackSliderObj.ondragend = dragEnd; | |
181 | |
182 // Onclick, switch playback to that track | |
183 trackSliderObj.onclick = function() { | |
184 // Get the track ID from the object ID | |
185 var id = Number(this.id.substr(13,2)); // Maximum theoretical tracks is 99! | |
186 audioEngineContext.selectedTrack(id); | |
187 }; | |
188 | |
189 canvas.appendChild(trackSliderObj); | |
190 }); | |
191 | |
192 | |
193 // Create pre and post test questions | |
194 | |
195 // Inject into HTML | |
196 insertPoint.innerHTML = null; // Clear the current schema | |
197 testContent.appendChild(title); // Insert the title | |
198 testContent.appendChild(interfaceButtons); | |
199 testContent.appendChild(sliderBox); | |
200 testContent.appendChild(feedbackHolder); | |
201 insertPoint.appendChild(testContent); | |
202 | |
203 var preTest = xmlDoc.find('PreTest'); | |
204 var postTest = xmlDoc.find('PostTest'); | |
205 preTest = preTest[0]; | |
206 postTest = postTest[0]; | |
207 if (preTest != undefined || postTest != undefined) | |
208 { | |
209 testContent.style.zIndex = 1; | |
210 var blank = document.createElement('div'); | |
211 blank.id = 'testHalt'; | |
212 blank.style.zIndex = 2; | |
213 blank.style.width = window.innerWidth + 'px'; | |
214 blank.style.height = window.innerHeight + 'px'; | |
215 blank.style.position = 'absolute'; | |
216 blank.style.top = '0'; | |
217 blank.style.left = '0'; | |
218 insertPoint.appendChild(blank); | |
219 } | |
220 | |
221 // Create Pre-Test Box | |
222 if (preTest != undefined && preTest.children.length >= 1) | |
223 { | |
224 | |
225 var preTestHolder = document.createElement('div'); | |
226 preTestHolder.id = 'preTestHolder'; | |
227 preTestHolder.style.zIndex = 2; | |
228 preTestHolder.style.width = '500px'; | |
229 preTestHolder.style.height = '250px'; | |
230 preTestHolder.style.backgroundColor = '#fff'; | |
231 preTestHolder.style.position = 'absolute'; | |
232 preTestHolder.style.left = (window.innerWidth/2)-250 + 'px'; | |
233 preTestHolder.style.top = (window.innerHeight/2)-125 + 'px'; | |
234 // Parse the first box | |
235 var preTestOption = document.createElement('div'); | |
236 preTestOption.id = 'preTest'; | |
237 preTestOption.style.marginTop = '25px'; | |
238 preTestOption.align = "center"; | |
239 var child = preTest.children[0]; | |
240 if (child.nodeName == 'statement') | |
241 { | |
242 preTestOption.innerHTML = '<span>'+child.innerHTML+'</span>'; | |
243 } else if (child.nodeName == 'question') | |
244 { | |
245 var questionId = child.attributes['id'].value; | |
246 var textHold = document.createElement('span'); | |
247 textHold.innerHTML = child.innerHTML; | |
248 textHold.id = questionId + 'response'; | |
249 var textEnter = document.createElement('textarea'); | |
250 preTestOption.appendChild(textHold); | |
251 preTestOption.appendChild(textEnter); | |
252 } | |
253 var nextButton = document.createElement('button'); | |
254 nextButton.id = 'preTestNext'; | |
255 nextButton.value = '1'; | |
256 nextButton.innerHTML = 'next'; | |
257 nextButton.style.position = 'relative'; | |
258 nextButton.style.left = '450px'; | |
259 nextButton.style.top = '175px'; | |
260 nextButton.onclick = function() { | |
261 // Need to find and parse preTest again! | |
262 var preTest = projectXML.find('PreTest')[0]; | |
263 // Check if current state is a question! | |
264 if (preTest.children[this.value-1].nodeName == 'question') { | |
265 var questionId = preTest.children[this.value-1].attributes['id'].value; | |
266 var questionHold = document.createElement('comment'); | |
267 var questionResponse = document.getElementById(questionId + 'response'); | |
268 questionHold.id = questionId; | |
269 questionHold.innerHTML = questionResponse.value; | |
270 preTestQuestions.appendChild(questionHold); | |
271 } | |
272 if (this.value < preTest.children.length) | |
273 { | |
274 // More to process | |
275 var child = preTest.children[this.value]; | |
276 if (child.nodeName == 'statement') | |
277 { | |
278 preTestOption.innerHTML = '<span>'+child.innerHTML+'</span>'; | |
279 } else if (child.nodeName == 'question') | |
280 { | |
281 var textHold = document.createElement('span'); | |
282 textHold.innerHTML = child.innerHTML; | |
283 var textEnter = document.createElement('textarea'); | |
284 textEnter.id = child.attributes['id'].value + 'response'; | |
285 preTestOption.innerHTML = null; | |
286 preTestOption.appendChild(textHold); | |
287 preTestOption.appendChild(textEnter); | |
288 } | |
289 } else { | |
290 // Time to clear | |
291 preTestHolder.style.zIndex = -1; | |
292 preTestHolder.style.visibility = 'hidden'; | |
293 var blank = document.getElementById('testHalt'); | |
294 blank.style.zIndex = -2; | |
295 blank.style.visibility = 'hidden'; | |
296 } | |
297 this.value++; | |
298 }; | |
299 | |
300 preTestHolder.appendChild(preTestOption); | |
301 preTestHolder.appendChild(nextButton); | |
302 insertPoint.appendChild(preTestHolder); | |
303 } | |
304 | |
305 } | |
306 | |
307 function dragEnd(ev) { | |
308 // Function call when a div has been dropped | |
309 if (ev.x >= 50 && ev.x < window.innerWidth-50) { | |
310 this.style.left = (ev.x)+'px'; | |
311 } else { | |
312 if (ev.x<50) { | |
313 this.style.left = '50px'; | |
314 } else { | |
315 this.style.left = window.innerWidth-50 + 'px'; | |
316 } | |
317 } | |
318 } | |
319 | |
320 // Only other global function which must be defined in the interface class. Determines how to create the XML document. | |
321 function interfaceXMLSave(){ | |
322 // Create the XML string to be exported with results | |
323 var xmlDoc = document.createElement("BrowserEvaluationResult"); | |
324 var trackSliderObjects = document.getElementsByClassName('track-slider'); | |
325 var commentObjects = document.getElementsByClassName('trackComment'); | |
326 var rateMin = 50; | |
327 var rateMax = window.innerWidth-50; | |
328 for (var i=0; i<trackSliderObjects.length; i++) | |
329 { | |
330 var trackObj = document.createElement("audioElement"); | |
331 trackObj.id = i; | |
332 trackObj.url = audioEngineContext.audioObjects[i].url; | |
333 var slider = document.createElement("Rating"); | |
334 var rate = Number(trackSliderObjects[i].style.left.substr(0,trackSliderObjects[i].style.left.length-2)); | |
335 rate = (rate-rateMin)/rateMax; | |
336 slider.innerHTML = Math.floor(rate*100); | |
337 var comment = document.createElement("Comment"); | |
338 comment.innerHTML = commentObjects[i].value; | |
339 trackObj.appendChild(slider); | |
340 trackObj.appendChild(comment); | |
341 xmlDoc.appendChild(trackObj); | |
342 } | |
343 | |
344 // Append Pre/Post Questions | |
345 xmlDoc.appendChild(preTestQuestions); | |
346 xmlDoc.appendChild(postTestQuestions); | |
347 | |
348 return xmlDoc; | |
349 } | |
350 |