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();