annotate interfaces/AB.js @ 22:1f375b7d75fd tip

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