Mercurial > hg > webaudioevaluationtool
comparison interfaces/discrete.js @ 2699:6350ae016862
#180. JSHint Discrete.js
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Mon, 13 Mar 2017 11:18:55 +0000 |
parents | 22efb2d04bc9 |
children | 87d9f785f1ec |
comparison
equal
deleted
inserted
replaced
2698:0562dcdfd5eb | 2699:6350ae016862 |
---|---|
1 /* globals interfaceContext, document, window, $, specification, audioEngineContext, console, window, testState, storage */ | |
1 // Once this is loaded and parsed, begin execution | 2 // Once this is loaded and parsed, begin execution |
2 loadInterface(); | 3 loadInterface(); |
3 | 4 |
4 function loadInterface() { | 5 function loadInterface() { |
5 // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, | 6 // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, |
17 title.align = "center"; | 18 title.align = "center"; |
18 var titleSpan = document.createElement('span'); | 19 var titleSpan = document.createElement('span'); |
19 titleSpan.id = "test-title"; | 20 titleSpan.id = "test-title"; |
20 | 21 |
21 // Set title to that defined in XML, else set to default | 22 // Set title to that defined in XML, else set to default |
22 if (titleAttr != undefined) { | 23 if (titleAttr !== undefined) { |
23 titleSpan.textContent = titleAttr; | 24 titleSpan.textContent = titleAttr; |
24 } else { | 25 } else { |
25 titleSpan.textContent = 'Listening test'; | 26 titleSpan.textContent = 'Listening test'; |
26 } | 27 } |
27 // Insert the titleSpan element into the title div element. | 28 // Insert the titleSpan element into the title div element. |
28 title.appendChild(titleSpan); | 29 title.appendChild(titleSpan); |
29 | 30 |
30 var pagetitle = document.createElement('div'); | 31 var pagetitle = document.createElement('div'); |
31 pagetitle.className = "pageTitle"; | 32 pagetitle.className = "pageTitle"; |
32 pagetitle.align = "center"; | 33 pagetitle.align = "center"; |
33 var titleSpan = document.createElement('span'); | 34 |
35 titleSpan = document.createElement('span'); | |
34 titleSpan.id = "pageTitle"; | 36 titleSpan.id = "pageTitle"; |
35 pagetitle.appendChild(titleSpan); | 37 pagetitle.appendChild(titleSpan); |
36 | 38 |
37 // Create Interface buttons! | 39 // Create Interface buttons! |
38 var interfaceButtons = document.createElement('div'); | 40 var interfaceButtons = document.createElement('div'); |
110 interfaceContext.insertPoint.appendChild(testContent); | 112 interfaceContext.insertPoint.appendChild(testContent); |
111 | 113 |
112 // Load the full interface | 114 // Load the full interface |
113 testState.initialise(); | 115 testState.initialise(); |
114 testState.advanceState(); | 116 testState.advanceState(); |
115 }; | 117 } |
116 | 118 |
117 function loadTest(page) { | 119 function loadTest(page) { |
118 // Called each time a new test page is to be build. The page specification node is the only item passed in | 120 // Called each time a new test page is to be build. The page specification node is the only item passed in |
119 var id = page.id; | 121 var id = page.id; |
120 | 122 |
126 } | 128 } |
127 interfaceObj = interfaceObj[0]; | 129 interfaceObj = interfaceObj[0]; |
128 | 130 |
129 // Set the page title | 131 // Set the page title |
130 if (typeof page.title == "string" && page.title.length > 0) { | 132 if (typeof page.title == "string" && page.title.length > 0) { |
131 document.getElementById("test-title").textContent = page.title | 133 document.getElementById("test-title").textContent = page.title; |
132 } | 134 } |
133 | 135 |
134 if (interfaceObj.title != null) { | 136 if (interfaceObj.title !== null) { |
135 document.getElementById("pageTitle").textContent = interfaceObj.title; | 137 document.getElementById("pageTitle").textContent = interfaceObj.title; |
136 } | 138 } |
137 | 139 |
138 // Delete outside reference | 140 // Delete outside reference |
139 document.getElementById("outside-reference-holder").innerHTML = ""; | 141 document.getElementById("outside-reference-holder").innerHTML = ""; |
140 | 142 |
141 var sliderBox = document.getElementById('slider-holder'); | 143 var sliderBox = document.getElementById('slider-holder'); |
142 sliderBox.innerHTML = ""; | 144 sliderBox.innerHTML = ""; |
143 | 145 |
144 var commentBoxPrefix = "Comment on track"; | 146 var commentBoxPrefix = "Comment on track"; |
145 if (interfaceObj.commentBoxPrefix != undefined) { | 147 if (interfaceObj.commentBoxPrefix !== undefined) { |
146 commentBoxPrefix = interfaceObj.commentBoxPrefix; | 148 commentBoxPrefix = interfaceObj.commentBoxPrefix; |
147 } | 149 } |
148 var loopPlayback = page.loop; | 150 var loopPlayback = page.loop; |
149 | 151 |
150 for (var option of interfaceObj.options) { | 152 interfaceObj.options.forEach(function (option) { |
151 if (option.type == "show") { | 153 if (option.type == "show") { |
152 switch (option.name) { | 154 switch (option.name) { |
153 case "playhead": | 155 case "playhead": |
154 var playbackHolder = document.getElementById('playback-holder'); | 156 var playbackHolder = document.getElementById('playback-holder'); |
155 if (playbackHolder == null) { | 157 if (playbackHolder === null) { |
156 playbackHolder = document.createElement('div'); | 158 playbackHolder = document.createElement('div'); |
157 playbackHolder.style.width = "100%"; | 159 playbackHolder.style.width = "100%"; |
158 playbackHolder.align = 'center'; | 160 playbackHolder.align = 'center'; |
159 playbackHolder.appendChild(interfaceContext.playhead.object); | 161 playbackHolder.appendChild(interfaceContext.playhead.object); |
160 feedbackHolder.appendChild(playbackHolder); | 162 feedbackHolder.appendChild(playbackHolder); |
161 } | 163 } |
162 break; | 164 break; |
163 case "page-count": | 165 case "page-count": |
164 var pagecountHolder = document.getElementById('page-count'); | 166 var pagecountHolder = document.getElementById('page-count'); |
165 if (pagecountHolder == null) { | 167 if (pagecountHolder === null) { |
166 pagecountHolder = document.createElement('div'); | 168 pagecountHolder = document.createElement('div'); |
167 pagecountHolder.id = 'page-count'; | 169 pagecountHolder.id = 'page-count'; |
168 } | 170 } |
169 pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; | 171 pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; |
170 var inject = document.getElementById('interface-buttons'); | 172 var inject = document.getElementById('interface-buttons'); |
171 inject.appendChild(pagecountHolder); | 173 inject.appendChild(pagecountHolder); |
172 break; | 174 break; |
173 case "volume": | 175 case "volume": |
174 if (document.getElementById('master-volume-holder') == null) { | 176 if (document.getElementById('master-volume-holder') === null) { |
175 feedbackHolder.appendChild(interfaceContext.volume.object); | 177 feedbackHolder.appendChild(interfaceContext.volume.object); |
176 } | 178 } |
177 break; | 179 break; |
178 case "comments": | 180 case "comments": |
179 interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); | 181 interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); |
180 break; | 182 break; |
181 } | 183 } |
182 } | 184 } |
183 } | 185 }); |
184 | 186 |
185 // Find all the audioElements from the audioHolder | 187 // Find all the audioElements from the audioHolder |
186 var index = 0; | 188 var index = 0; |
187 var interfaceScales = page.interfaces[0].scales; | 189 var interfaceScales = page.interfaces[0].scales; |
188 var labelType = page.label; | 190 var labelType = page.label; |
221 | 223 |
222 function discreteObject(audioObject, label, interfaceScales) { | 224 function discreteObject(audioObject, label, interfaceScales) { |
223 // An example node, you can make this however you want for each audioElement. | 225 // An example node, you can make this however you want for each audioElement. |
224 // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following | 226 // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following |
225 // You attach them by calling audioObject.bindInterface( ) | 227 // You attach them by calling audioObject.bindInterface( ) |
226 if (interfaceScales == null || interfaceScales.length == 0) { | 228 if (interfaceScales === null || interfaceScales.length === 0) { |
227 console.log("WARNING: The discrete radio's are built depending on the number of scale points specified! Ensure you have some specified. Defaulting to 5 for now!"); | 229 console.log("WARNING: The discrete radio's are built depending on the number of scale points specified! Ensure you have some specified. Defaulting to 5 for now!"); |
228 numOptions = 5; | 230 var numOptions = 5; |
229 } | 231 } |
230 this.parent = audioObject; | 232 this.parent = audioObject; |
231 | 233 |
232 this.holder = document.createElement('div'); | 234 this.holder = document.createElement('div'); |
233 this.title = document.createElement('div'); | 235 this.title = document.createElement('div'); |
244 this.title.textContent = label; | 246 this.title.textContent = label; |
245 this.title.className = 'track-slider-title'; | 247 this.title.className = 'track-slider-title'; |
246 | 248 |
247 this.discreteHolder.className = "track-slider-range"; | 249 this.discreteHolder.className = "track-slider-range"; |
248 this.discreteHolder.style.width = window.innerWidth - 500 + 'px'; | 250 this.discreteHolder.style.width = window.innerWidth - 500 + 'px'; |
251 this.radioClicked = function (event) { | |
252 var time = audioEngineContext.timer.getTestTime(); | |
253 if (audioEngineContext.status === 0) { | |
254 event.currentTarget.checked = false; | |
255 return; | |
256 } | |
257 var id = this.parent.id; | |
258 var checkedelement = this.discretes.find(function (elem) { | |
259 return elem.checked; | |
260 }); | |
261 var position = checkedelement.getAttribute("position") / 100.0; | |
262 this.parent.metric.moved(time, checkedelement); | |
263 console.log('slider ' + id + ' moved to ' + position + ' (' + time + ')'); | |
264 | |
265 }; | |
266 this.handleEvent = function (event) { | |
267 if (event.currentTarget.getAttribute("name") === this.parent.specification.id) { | |
268 this.radioClicked(event); | |
269 } | |
270 }; | |
249 for (var i = 0; i < interfaceScales.length; i++) { | 271 for (var i = 0; i < interfaceScales.length; i++) { |
250 var node = document.createElement('input'); | 272 var node = document.createElement('input'); |
251 node.setAttribute('type', 'radio'); | 273 node.setAttribute('type', 'radio'); |
252 node.className = 'track-radio'; | 274 node.className = 'track-radio'; |
253 node.disabled = true; | 275 node.disabled = true; |
254 node.setAttribute('position', interfaceScales[i].position); | 276 node.setAttribute('position', interfaceScales[i].position); |
255 node.setAttribute('name', audioObject.specification.id); | 277 node.setAttribute('name', audioObject.specification.id); |
256 node.setAttribute('id', audioObject.specification.id + '-' + String(i)); | 278 node.setAttribute('id', audioObject.specification.id + '-' + String(i)); |
257 this.discretes.push(node); | 279 this.discretes.push(node); |
258 this.discreteHolder.appendChild(node); | 280 this.discreteHolder.appendChild(node); |
259 node.onclick = function (event) { | 281 node.addEventListener("click", this); |
260 if (audioEngineContext.status == 0) { | |
261 event.currentTarget.checked = false; | |
262 return; | |
263 } | |
264 var time = audioEngineContext.timer.getTestTime(); | |
265 var id = Number(event.currentTarget.parentNode.parentNode.getAttribute('trackIndex')); | |
266 var value = event.currentTarget.getAttribute('position') / 100.0; | |
267 audioEngineContext.audioObjects[id].metric.moved(time, value); | |
268 console.log('slider ' + id + ' moved to ' + value + ' (' + time + ')'); | |
269 }; | |
270 } | 282 } |
271 | 283 |
272 this.play.className = 'track-slider-button'; | 284 this.play.className = 'track-slider-button'; |
273 this.play.textContent = "Loading..."; | 285 this.play.textContent = "Loading..."; |
274 this.play.value = audioObject.id; | 286 this.play.value = audioObject.id; |
298 this.enable = function () { | 310 this.enable = function () { |
299 // This is used to tell the interface object that playback of this node is ready | 311 // This is used to tell the interface object that playback of this node is ready |
300 this.play.disabled = false; | 312 this.play.disabled = false; |
301 this.play.textContent = "Play"; | 313 this.play.textContent = "Play"; |
302 $(this.slider).removeClass('track-slider-disabled'); | 314 $(this.slider).removeClass('track-slider-disabled'); |
303 for (var radio of this.discretes) { | 315 this.discretes.forEach(function (elem) { |
304 radio.disabled = false; | 316 elem.disabled = false; |
305 } | 317 }); |
306 }; | 318 }; |
307 this.updateLoading = function (progress) { | 319 this.updateLoading = function (progress) { |
308 // progress is a value from 0 to 100 indicating the current download state of media files | 320 // progress is a value from 0 to 100 indicating the current download state of media files |
309 if (progress != 100) { | 321 if (progress != 100) { |
310 progress = String(progress); | 322 progress = String(progress); |
320 this.play.setAttribute("playstate", "playing"); | 332 this.play.setAttribute("playstate", "playing"); |
321 $(".track-slider").removeClass('track-slider-playing'); | 333 $(".track-slider").removeClass('track-slider-playing'); |
322 $(this.holder).addClass('track-slider-playing'); | 334 $(this.holder).addClass('track-slider-playing'); |
323 var outsideReference = document.getElementById('outside-reference'); | 335 var outsideReference = document.getElementById('outside-reference'); |
324 this.play.textContent = "Listening"; | 336 this.play.textContent = "Listening"; |
325 if (outsideReference != null) { | 337 if (outsideReference !== null) { |
326 $(outsideReference).removeClass('track-slider-playing'); | 338 $(outsideReference).removeClass('track-slider-playing'); |
327 } | 339 } |
328 if (this.parent.specification.parent.playOne || specification.playOne) { | 340 if (this.parent.specification.parent.playOne || specification.playOne) { |
329 $('.track-slider-button').text = "Wait"; | 341 $('.track-slider-button').text = "Wait"; |
330 $('.track-slider-button').attr("disabled", "true"); | 342 $('.track-slider-button').attr("disabled", "true"); |
331 } | 343 } |
332 } | 344 }; |
333 this.stopPlayback = function () { | 345 this.stopPlayback = function () { |
334 // Called by audioObject when playback stops | 346 // Called by audioObject when playback stops |
335 if (this.play.getAttribute("playstate") == "playing") { | 347 if (this.play.getAttribute("playstate") == "playing") { |
336 this.play.setAttribute("playstate", "ready"); | 348 this.play.setAttribute("playstate", "ready"); |
337 $(this.holder).removeClass('track-slider-playing'); | 349 $(this.holder).removeClass('track-slider-playing'); |
338 $('.track-slider-button').text = "Play"; | 350 $('.track-slider-button').text = "Play"; |
339 this.play.textContent = "Play"; | 351 this.play.textContent = "Play"; |
340 $('.track-slider-button').removeAttr("disabled"); | 352 $('.track-slider-button').removeAttr("disabled"); |
341 } | 353 } |
342 } | 354 }; |
343 | 355 |
344 this.getValue = function () { | 356 this.getValue = function () { |
345 // Return the current value of the object. If there is no value, return -1 | 357 // Return the current value of the object. If there is no value, return -1 |
346 var value = -1; | 358 var value = -1; |
347 for (var i = 0; i < this.discretes.length; i++) { | 359 for (var i = 0; i < this.discretes.length; i++) { |
348 if (this.discretes[i].checked == true) { | 360 if (this.discretes[i].checked === true) { |
349 value = this.discretes[i].getAttribute('position') / 100.0; | 361 value = this.discretes[i].getAttribute('position') / 100.0; |
350 break; | 362 break; |
351 } | 363 } |
352 } | 364 } |
353 return value; | 365 return value; |
372 }; | 384 }; |
373 this.error = function () { | 385 this.error = function () { |
374 // audioObject has an error!! | 386 // audioObject has an error!! |
375 this.playback.textContent = "Error"; | 387 this.playback.textContent = "Error"; |
376 $(this.playback).addClass("error-colour"); | 388 $(this.playback).addClass("error-colour"); |
377 } | 389 }; |
378 }; | 390 } |
379 | 391 |
380 function resizeWindow(event) { | 392 function resizeWindow(event) { |
381 // Called on every window resize event, use this to scale your page properly | 393 // Called on every window resize event, use this to scale your page properly |
382 var numObj = document.getElementsByClassName('track-slider').length; | 394 var numObj = document.getElementsByClassName('track-slider').length; |
383 var totalHeight = (numObj * 66) - 30; | 395 var totalHeight = (numObj * 66) - 30; |
413 var width = canvas.width; | 425 var width = canvas.width; |
414 var textHolder = document.getElementById('scale-text-holder'); | 426 var textHolder = document.getElementById('scale-text-holder'); |
415 textHolder.innerHTML = ""; | 427 textHolder.innerHTML = ""; |
416 ctx.fillStyle = "#000000"; | 428 ctx.fillStyle = "#000000"; |
417 ctx.setLineDash([1, 4]); | 429 ctx.setLineDash([1, 4]); |
418 for (var scale of scales) { | 430 scales.forEach(function (scale) { |
419 var posPercent = scale.position / 100.0; | 431 var posPercent = scale.position / 100.0; |
420 var posPix = Math.round(width * posPercent); | 432 var posPix = Math.round(width * posPercent); |
421 if (posPix <= 0) { | 433 if (posPix <= 0) { |
422 posPix = 1; | 434 posPix = 1; |
423 } | 435 } |
435 text.appendChild(textC); | 447 text.appendChild(textC); |
436 text.className = "scale-text"; | 448 text.className = "scale-text"; |
437 textHolder.appendChild(text); | 449 textHolder.appendChild(text); |
438 text.style.width = $(text.children[0]).width() + 'px'; | 450 text.style.width = $(text.children[0]).width() + 'px'; |
439 text.style.left = (posPix + 150 - ($(text).width() / 2)) + 'px'; | 451 text.style.left = (posPix + 150 - ($(text).width() / 2)) + 'px'; |
440 } | 452 }); |
441 } | 453 } |
442 | 454 |
443 function buttonSubmitClick() // TODO: Only when all songs have been played! | 455 function buttonSubmitClick() // TODO: Only when all songs have been played! |
444 { | 456 { |
445 var checks = testState.currentStateMap.interfaces[0].options, | 457 var checks = testState.currentStateMap.interfaces[0].options, |
446 canContinue = true; | 458 canContinue = true; |
447 | 459 |
448 // Check that the anchor and reference objects are correctly placed | 460 // Check that the anchor and reference objects are correctly placed |
449 if (interfaceContext.checkHiddenAnchor() == false) { | 461 if (interfaceContext.checkHiddenAnchor() === false) { |
450 return; | 462 return; |
451 } | 463 } |
452 if (interfaceContext.checkHiddenReference() == false) { | 464 if (interfaceContext.checkHiddenReference() === false) { |
453 return; | 465 return; |
454 } | 466 } |
455 | 467 |
456 for (var i = 0; i < checks.length; i++) { | 468 for (var i = 0; i < checks.length; i++) { |
469 var checkState; | |
457 if (checks[i].type == 'check') { | 470 if (checks[i].type == 'check') { |
458 switch (checks[i].name) { | 471 switch (checks[i].name) { |
459 case 'fragmentPlayed': | 472 case 'fragmentPlayed': |
460 // Check if all fragments have been played | 473 // Check if all fragments have been played |
461 var checkState = interfaceContext.checkAllPlayed(); | 474 checkState = interfaceContext.checkAllPlayed(); |
462 if (checkState == false) { | |
463 canContinue = false; | |
464 } | |
465 break; | 475 break; |
466 case 'fragmentFullPlayback': | 476 case 'fragmentFullPlayback': |
467 // Check all fragments have been played to their full length | 477 // Check all fragments have been played to their full length |
468 var checkState = interfaceContext.checkAllPlayed(); | 478 checkState = interfaceContext.checkAllPlayed(); |
469 if (checkState == false) { | |
470 canContinue = false; | |
471 } | |
472 console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); | 479 console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); |
473 break; | 480 break; |
474 case 'fragmentMoved': | 481 case 'fragmentMoved': |
475 // Check all fragment sliders have been moved. | 482 // Check all fragment sliders have been moved. |
476 var checkState = interfaceContext.checkAllMoved(); | 483 checkState = interfaceContext.checkAllMoved(); |
477 if (checkState == false) { | |
478 canContinue = false; | |
479 } | |
480 break; | 484 break; |
481 case 'fragmentComments': | 485 case 'fragmentComments': |
482 // Check all fragment sliders have been moved. | 486 // Check all fragment sliders have been moved. |
483 var checkState = interfaceContext.checkAllCommented(); | 487 checkState = interfaceContext.checkAllCommented(); |
484 if (checkState == false) { | |
485 canContinue = false; | |
486 } | |
487 break; | 488 break; |
488 case 'scalerange': | 489 case 'scalerange': |
489 // Check the scale has been used effectively | 490 // Check the scale has been used effectively |
490 var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); | 491 checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); |
491 if (checkState == false) { | |
492 canContinue = false; | |
493 } | |
494 break; | 492 break; |
495 default: | 493 default: |
496 console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); | 494 console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); |
497 break; | 495 break; |
498 } | 496 } |
499 | 497 if (checkState === false) { |
498 canContinue = false; | |
499 } | |
500 } | 500 } |
501 if (!canContinue) { | 501 if (!canContinue) { |
502 break; | 502 break; |
503 } | 503 } |
504 } | 504 } |
507 if (audioEngineContext.status == 1) { | 507 if (audioEngineContext.status == 1) { |
508 var playback = document.getElementById('playback-button'); | 508 var playback = document.getElementById('playback-button'); |
509 playback.click(); | 509 playback.click(); |
510 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options | 510 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options |
511 } else { | 511 } else { |
512 if (audioEngineContext.timer.testStarted == false) { | 512 if (audioEngineContext.timer.testStarted === false) { |
513 interfaceContext.lightbox.post("Warning", 'You have not started the test! Please press start to begin the test!'); | 513 interfaceContext.lightbox.post("Warning", 'You have not started the test! Please press start to begin the test!'); |
514 return; | 514 return; |
515 } | 515 } |
516 } | 516 } |
517 testState.advanceState(); | 517 testState.advanceState(); |