annotate ape.js @ 1562:1ab660334f94

Ready for merge into main.
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Wed, 17 Jun 2015 16:42:57 +0100
parents bd06a7dc0418
children a049c6cf7eb3
rev   line source
nickjillings@1556 1 /**
nickjillings@1556 2 * ape.js
nickjillings@1556 3 * Create the APE interface
nickjillings@1556 4 */
nickjillings@1556 5
nickjillings@1556 6 // preTest - In preTest state
nickjillings@1556 7 // testRun-ID - In test running, test Id number at the end 'testRun-2'
nickjillings@1556 8 // testRunPost-ID - Post test of test ID
nickjillings@1556 9 // testRunPre-ID - Pre-test of test ID
nickjillings@1556 10 // postTest - End of test, final submission!
nickjillings@1556 11
nickjillings@1556 12
nickjillings@1556 13 // Once this is loaded and parsed, begin execution
nickjillings@1556 14 loadInterface();
nickjillings@1556 15
nickjillings@1556 16 function loadInterface() {
nickjillings@1556 17
nickjillings@1556 18 // Get the dimensions of the screen available to the page
nickjillings@1556 19 var width = window.innerWidth;
nickjillings@1556 20 var height = window.innerHeight;
nickjillings@1556 21
nickjillings@1556 22 // The injection point into the HTML page
nickjillings@1556 23 interfaceContext.insertPoint = document.getElementById("topLevelBody");
nickjillings@1556 24 var testContent = document.createElement('div');
nickjillings@1556 25
nickjillings@1556 26 testContent.id = 'testContent';
nickjillings@1556 27
nickjillings@1556 28
nickjillings@1556 29 // Create APE specific metric functions
nickjillings@1556 30 audioEngineContext.metric.initialiseTest = function()
nickjillings@1556 31 {
nickjillings@1556 32 };
nickjillings@1556 33
nickjillings@1556 34 audioEngineContext.metric.sliderMoved = function()
nickjillings@1556 35 {
nickjillings@1556 36
nickjillings@1556 37 var id = this.data;
nickjillings@1556 38 this.data = -1;
nickjillings@1556 39 var position = convSliderPosToRate(id);
nickjillings@1556 40 console.log('slider ' + id + ': '+ position + ' (' + time + ')'); // DEBUG/SAFETY: show position and slider id
nickjillings@1556 41 if (audioEngineContext.timer.testStarted)
nickjillings@1556 42 {
nickjillings@1556 43 audioEngineContext.audioObjects[id].metric.moved(time,position);
nickjillings@1556 44 }
nickjillings@1556 45 };
nickjillings@1556 46
nickjillings@1556 47 audioEngineContext.metric.sliderPlayed = function(id)
nickjillings@1556 48 {
nickjillings@1556 49 var time = audioEngineContext.timer.getTestTime();
nickjillings@1556 50 if (audioEngineContext.timer.testStarted)
nickjillings@1556 51 {
nickjillings@1556 52 if (this.lastClicked >= 0)
nickjillings@1556 53 {
nickjillings@1556 54 audioEngineContext.audioObjects[this.lastClicked].metric.listening(time);
nickjillings@1556 55 }
nickjillings@1556 56 this.lastClicked = id;
nickjillings@1556 57 audioEngineContext.audioObjects[id].metric.listening(time);
nickjillings@1556 58 }
nickjillings@1556 59 console.log('slider ' + id + ' played (' + time + ')'); // DEBUG/SAFETY: show played slider id
nickjillings@1556 60 };
nickjillings@1556 61
nickjillings@1557 62 // Bindings for interfaceContext
nickjillings@1557 63 Interface.prototype.checkAllPlayed = function()
nickjillings@1557 64 {
nickjillings@1557 65 hasBeenPlayed = audioEngineContext.checkAllPlayed();
nickjillings@1557 66 if (hasBeenPlayed.length > 0) // if a fragment has not been played yet
nickjillings@1557 67 {
nickjillings@1557 68 str = "";
nickjillings@1557 69 if (hasBeenPlayed.length > 1) {
nickjillings@1557 70 for (var i=0; i<hasBeenPlayed.length; i++) {
nickjillings@1557 71 str = str + hasBeenPlayed[i];
nickjillings@1557 72 if (i < hasBeenPlayed.length-2){
nickjillings@1557 73 str += ", ";
nickjillings@1557 74 } else if (i == hasBeenPlayed.length-2) {
nickjillings@1557 75 str += " or ";
nickjillings@1557 76 }
nickjillings@1557 77 }
nickjillings@1557 78 alert('You have not played fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 79 } else {
nickjillings@1557 80 alert('You have not played fragment ' + hasBeenPlayed[0] + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 81 }
nickjillings@1557 82 return false;
nickjillings@1557 83 }
nickjillings@1557 84 return true;
nickjillings@1561 85 };
nickjillings@1557 86
nickjillings@1557 87 Interface.prototype.checkAllMoved = function() {
nickjillings@1557 88 var audioObjs = audioEngineContext.audioObjects;
nickjillings@1557 89 var state = true;
nickjillings@1557 90 var strNums = [];
nickjillings@1557 91 for (var i=0; i<audioObjs.length; i++)
nickjillings@1557 92 {
nickjillings@1557 93 if (audioObjs[i].metric.wasMoved == false) {
nickjillings@1557 94 state = false;
nickjillings@1557 95 strNums.push(i);
nickjillings@1557 96 }
nickjillings@1557 97 }
nickjillings@1557 98 if (state == false) {
nickjillings@1557 99 if (strNums.length > 1) {
nickjillings@1557 100 var str = "";
nickjillings@1557 101 for (var i=0; i<strNums.length; i++) {
nickjillings@1557 102 str = str + strNums[i];
nickjillings@1557 103 if (i < strNums.length-2){
nickjillings@1557 104 str += ", ";
nickjillings@1557 105 } else if (i == strNums.length-2) {
nickjillings@1557 106 str += " or ";
nickjillings@1557 107 }
nickjillings@1557 108 }
nickjillings@1557 109 alert('You have not moved fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 110 } else {
nickjillings@1557 111 alert('You have not moved fragment ' + strNums[0] + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 112 }
nickjillings@1557 113 }
nickjillings@1557 114 return state;
nickjillings@1561 115 };
nickjillings@1557 116
nickjillings@1557 117 Interface.prototype.checkAllCommented = function() {
nickjillings@1557 118 var audioObjs = audioEngineContext.audioObjects;
nickjillings@1557 119 var audioHolder = testState.stateMap[testState.stateIndex];
nickjillings@1557 120 var state = true;
nickjillings@1557 121 if (audioHolder.elementComments) {
nickjillings@1557 122 var strNums = [];
nickjillings@1557 123 for (var i=0; i<audioObjs.length; i++)
nickjillings@1557 124 {
nickjillings@1557 125 if (audioObjs[i].commentDOM.trackCommentBox.value.length == 0) {
nickjillings@1557 126 state = false;
nickjillings@1557 127 strNums.push(i);
nickjillings@1557 128 }
nickjillings@1557 129 }
nickjillings@1557 130 if (state == false) {
nickjillings@1557 131 if (strNums.length > 1) {
nickjillings@1557 132 var str = "";
nickjillings@1557 133 for (var i=0; i<strNums.length; i++) {
nickjillings@1557 134 str = str + strNums[i];
nickjillings@1557 135 if (i < strNums.length-2){
nickjillings@1557 136 str += ", ";
nickjillings@1557 137 } else if (i == strNums.length-2) {
nickjillings@1557 138 str += " or ";
nickjillings@1557 139 }
nickjillings@1557 140 }
nickjillings@1557 141 alert('You have not commented on fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 142 } else {
nickjillings@1557 143 alert('You have not commented on fragment ' + strNums[0] + ' yet. Please listen, rate and comment all samples before submitting.');
nickjillings@1557 144 }
nickjillings@1557 145 }
nickjillings@1557 146 }
nickjillings@1557 147 return state;
nickjillings@1561 148 };
nickjillings@1557 149
nickjillings@1556 150 // Bindings for audioObjects
nickjillings@1556 151
nickjillings@1556 152 // Create the top div for the Title element
nickjillings@1556 153 var titleAttr = specification.title;
nickjillings@1556 154 var title = document.createElement('div');
nickjillings@1556 155 title.className = "title";
nickjillings@1556 156 title.align = "center";
nickjillings@1556 157 var titleSpan = document.createElement('span');
nickjillings@1556 158
nickjillings@1556 159 // Set title to that defined in XML, else set to default
nickjillings@1556 160 if (titleAttr != undefined) {
nickjillings@1556 161 titleSpan.textContent = titleAttr;
nickjillings@1556 162 } else {
nickjillings@1556 163 titleSpan.textContent = 'Listening test';
nickjillings@1556 164 }
nickjillings@1556 165 // Insert the titleSpan element into the title div element.
nickjillings@1556 166 title.appendChild(titleSpan);
nickjillings@1556 167
nickjillings@1556 168 var pagetitle = document.createElement('div');
nickjillings@1556 169 pagetitle.className = "pageTitle";
nickjillings@1556 170 pagetitle.align = "center";
nickjillings@1556 171 var titleSpan = document.createElement('span');
nickjillings@1556 172 titleSpan.id = "pageTitle";
nickjillings@1556 173 pagetitle.appendChild(titleSpan);
nickjillings@1556 174
nickjillings@1556 175 // Create Interface buttons!
nickjillings@1556 176 var interfaceButtons = document.createElement('div');
nickjillings@1556 177 interfaceButtons.id = 'interface-buttons';
nickjillings@1556 178
nickjillings@1556 179 // Create playback start/stop points
nickjillings@1556 180 var playback = document.createElement("button");
nickjillings@1556 181 playback.innerHTML = 'Stop';
nickjillings@1556 182 playback.id = 'playback-button';
nickjillings@1556 183 // onclick function. Check if it is playing or not, call the correct function in the
nickjillings@1556 184 // audioEngine, change the button text to reflect the next state.
nickjillings@1556 185 playback.onclick = function() {
nickjillings@1556 186 if (audioEngineContext.status == 1) {
nickjillings@1556 187 audioEngineContext.stop();
nickjillings@1556 188 this.innerHTML = 'Stop';
nickjillings@1556 189 var time = audioEngineContext.timer.getTestTime();
nickjillings@1556 190 console.log('Stopped at ' + time); // DEBUG/SAFETY
nickjillings@1556 191 }
nickjillings@1556 192 };
nickjillings@1556 193 // Create Submit (save) button
nickjillings@1556 194 var submit = document.createElement("button");
nickjillings@1556 195 submit.innerHTML = 'Submit';
nickjillings@1556 196 submit.onclick = buttonSubmitClick;
nickjillings@1556 197 submit.id = 'submit-button';
nickjillings@1556 198 // Append the interface buttons into the interfaceButtons object.
nickjillings@1556 199 interfaceButtons.appendChild(playback);
nickjillings@1556 200 interfaceButtons.appendChild(submit);
nickjillings@1556 201
nickjillings@1556 202 // Now create the slider and HTML5 canvas boxes
nickjillings@1556 203
nickjillings@1556 204 // Create the div box to center align
nickjillings@1556 205 var sliderBox = document.createElement('div');
nickjillings@1556 206 sliderBox.className = 'sliderCanvasDiv';
nickjillings@1556 207 sliderBox.id = 'sliderCanvasHolder';
nickjillings@1556 208
nickjillings@1556 209 // Create the slider box to hold the slider elements
nickjillings@1556 210 var canvas = document.createElement('div');
nickjillings@1556 211 canvas.id = 'slider';
nickjillings@1556 212 canvas.align = "left";
nickjillings@1556 213 canvas.addEventListener('dragover',function(event){
nickjillings@1556 214 event.preventDefault();
nickjillings@1556 215 return false;
nickjillings@1556 216 },false);
nickjillings@1556 217 var sliderMargin = document.createAttribute('marginsize');
nickjillings@1556 218 sliderMargin.nodeValue = 42; // Set default margins to 42px either side
nickjillings@1556 219 // Must have a known EXACT width, as this is used later to determine the ratings
nickjillings@1556 220 var w = (Number(sliderMargin.nodeValue)+8)*2;
nickjillings@1556 221 canvas.style.width = width - w +"px";
nickjillings@1556 222 canvas.style.marginLeft = sliderMargin.nodeValue +'px';
nickjillings@1556 223 canvas.setAttributeNode(sliderMargin);
nickjillings@1556 224 sliderBox.appendChild(canvas);
nickjillings@1556 225
nickjillings@1556 226 // Create the div to hold any scale objects
nickjillings@1556 227 var scale = document.createElement('div');
nickjillings@1556 228 scale.className = 'sliderScale';
nickjillings@1556 229 scale.id = 'sliderScaleHolder';
nickjillings@1556 230 scale.align = 'left';
nickjillings@1556 231 sliderBox.appendChild(scale);
nickjillings@1556 232
nickjillings@1556 233 // Global parent for the comment boxes on the page
nickjillings@1556 234 var feedbackHolder = document.createElement('div');
nickjillings@1556 235 feedbackHolder.id = 'feedbackHolder';
nickjillings@1556 236
nickjillings@1556 237 testContent.style.zIndex = 1;
nickjillings@1556 238 interfaceContext.insertPoint.innerHTML = null; // Clear the current schema
nickjillings@1556 239
nickjillings@1556 240 // Inject into HTML
nickjillings@1556 241 testContent.appendChild(title); // Insert the title
nickjillings@1556 242 testContent.appendChild(pagetitle);
nickjillings@1556 243 testContent.appendChild(interfaceButtons);
nickjillings@1556 244 testContent.appendChild(sliderBox);
nickjillings@1556 245 testContent.appendChild(feedbackHolder);
nickjillings@1556 246 interfaceContext.insertPoint.appendChild(testContent);
nickjillings@1556 247
nickjillings@1556 248 // Load the full interface
nickjillings@1556 249 testState.initialise();
nickjillings@1556 250 testState.advanceState();
nickjillings@1556 251
nickjillings@1556 252 }
nickjillings@1556 253
nickjillings@1556 254 function loadTest(audioHolderObject)
nickjillings@1556 255 {
nickjillings@1556 256
nickjillings@1556 257 // Reset audioEngineContext.Metric globals for new test
nickjillings@1556 258 audioEngineContext.newTestPage();
nickjillings@1556 259
nickjillings@1556 260 var id = audioHolderObject.id;
nickjillings@1556 261
nickjillings@1556 262 var feedbackHolder = document.getElementById('feedbackHolder');
nickjillings@1556 263 var canvas = document.getElementById('slider');
nickjillings@1556 264 feedbackHolder.innerHTML = null;
nickjillings@1556 265 canvas.innerHTML = null;
nickjillings@1556 266
nickjillings@1562 267 //var playbackHolder = document.createElement('div');
nickjillings@1562 268 //playbackHolder.style.width = "100%";
nickjillings@1562 269 //playbackHolder.align = 'center';
nickjillings@1562 270 //playbackHolder.appendChild(interfaceContext.playhead.object);
nickjillings@1562 271 //feedbackHolder.appendChild(playbackHolder);
nickjillings@1556 272 // Setup question title
nickjillings@1556 273 var interfaceObj = audioHolderObject.interfaces;
nickjillings@1556 274 var commentBoxPrefix = "Comment on track";
nickjillings@1556 275 if (interfaceObj.length != 0) {
nickjillings@1556 276 interfaceObj = interfaceObj[0];
nickjillings@1556 277 var titleNode = interfaceObj.title;
nickjillings@1556 278 if (titleNode != undefined)
nickjillings@1556 279 {
nickjillings@1556 280 document.getElementById('pageTitle').textContent = titleNode;
nickjillings@1556 281 }
nickjillings@1556 282 var positionScale = canvas.style.width.substr(0,canvas.style.width.length-2);
nickjillings@1556 283 var offset = Number(document.getElementById('slider').attributes['marginsize'].value);
nickjillings@1556 284 var scale = document.getElementById('sliderScaleHolder');
nickjillings@1556 285 scale.innerHTML = null;
nickjillings@1556 286 $(interfaceObj.scale).each(function(index,scaleObj){
nickjillings@1556 287 var value = document.createAttribute('value');
nickjillings@1556 288 var position = Number(scaleObj[0])*0.01;
nickjillings@1556 289 value.nodeValue = position;
nickjillings@1556 290 var pixelPosition = (position*positionScale)+offset;
nickjillings@1556 291 var scaleDOM = document.createElement('span');
nickjillings@1556 292 scaleDOM.textContent = scaleObj[1];
nickjillings@1556 293 scale.appendChild(scaleDOM);
nickjillings@1556 294 scaleDOM.style.left = Math.floor((pixelPosition-($(scaleDOM).width()/2)))+'px';
nickjillings@1556 295 scaleDOM.setAttributeNode(value);
nickjillings@1556 296 });
nickjillings@1556 297
nickjillings@1556 298 if (interfaceObj.commentBoxPrefix != undefined) {
nickjillings@1556 299 commentBoxPrefix = interfaceObj.commentBoxPrefix;
nickjillings@1556 300 }
nickjillings@1556 301 }
nickjillings@1556 302
nickjillings@1556 303 /// CHECK FOR SAMPLE RATE COMPATIBILITY
nickjillings@1556 304 if (audioHolderObject.sampleRate != undefined) {
nickjillings@1556 305 if (Number(audioHolderObject.sampleRate) != audioContext.sampleRate) {
nickjillings@1556 306 var errStr = 'Sample rates do not match! Requested '+Number(audioHolderObject.sampleRate)+', got '+audioContext.sampleRate+'. Please set the sample rate to match before completing this test.';
nickjillings@1556 307 alert(errStr);
nickjillings@1556 308 return;
nickjillings@1556 309 }
nickjillings@1556 310 }
nickjillings@1556 311
nickjillings@1556 312 var commentShow = audioHolderObject.elementComments;
nickjillings@1556 313
nickjillings@1556 314 var loopPlayback = audioHolderObject.loop;
nickjillings@1556 315
nickjillings@1556 316 audioEngineContext.loopPlayback = loopPlayback;
nickjillings@1556 317 // Create AudioEngine bindings for playback
nickjillings@1556 318 audioEngineContext.selectedTrack = function(id) {
nickjillings@1556 319 console.log('Deprecated');
nickjillings@1556 320 };
nickjillings@1556 321
nickjillings@1556 322 currentTestHolder = document.createElement('audioHolder');
nickjillings@1556 323 currentTestHolder.id = audioHolderObject.id;
nickjillings@1556 324 currentTestHolder.repeatCount = audioHolderObject.repeatCount;
nickjillings@1556 325
nickjillings@1556 326 var randomise = audioHolderObject.randomiseOrder;
nickjillings@1556 327
nickjillings@1556 328 var audioElements = audioHolderObject.audioElements;
nickjillings@1556 329 currentTrackOrder = [];
nickjillings@1556 330 if (randomise) {
nickjillings@1556 331 audioHolderObject.audioElements = randomiseOrder(audioHolderObject.audioElements);
nickjillings@1556 332 }
nickjillings@1556 333
nickjillings@1556 334 // Delete any previous audioObjects associated with the audioEngine
nickjillings@1556 335 audioEngineContext.audioObjects = [];
nickjillings@1556 336 interfaceContext.deleteCommentBoxes();
nickjillings@1556 337
nickjillings@1556 338 // Find all the audioElements from the audioHolder
nickjillings@1556 339 $(audioHolderObject.audioElements).each(function(index,element){
nickjillings@1556 340 // Find URL of track
nickjillings@1556 341 // In this jQuery loop, variable 'this' holds the current audioElement.
nickjillings@1556 342
nickjillings@1556 343 // Now load each audio sample. First create the new track by passing the full URL
nickjillings@1556 344 var trackURL = audioHolderObject.hostURL + element.url;
nickjillings@1556 345 var audioObject = audioEngineContext.newTrack(element);
nickjillings@1556 346
nickjillings@1556 347 var node = interfaceContext.createCommentBox(audioObject);
nickjillings@1556 348
nickjillings@1556 349 // Create a slider per track
nickjillings@1556 350 audioObject.interfaceDOM = new sliderObject(audioObject);
nickjillings@1556 351
nickjillings@1556 352 // Distribute it randomnly
nickjillings@1556 353 var w = window.innerWidth - (offset+8)*2;
nickjillings@1556 354 w = Math.random()*w;
nickjillings@1556 355 w = Math.floor(w+(offset+8));
nickjillings@1556 356 audioObject.interfaceDOM.trackSliderObj.style.left = w+'px';
nickjillings@1556 357
nickjillings@1556 358 canvas.appendChild(audioObject.interfaceDOM.trackSliderObj);
nickjillings@1556 359 audioObject.metric.initialised(convSliderPosToRate(audioObject.interfaceDOM.trackSliderObj));
nickjillings@1556 360
nickjillings@1556 361 });
nickjillings@1556 362 if (commentShow) {
nickjillings@1556 363 interfaceContext.showCommentBoxes(feedbackHolder,true);
nickjillings@1556 364 }
nickjillings@1556 365
nickjillings@1556 366 $(audioHolderObject.commentQuestions).each(function(index,element) {
nickjillings@1556 367 var node = interfaceContext.createCommentQuestion(element);
nickjillings@1556 368 feedbackHolder.appendChild(node.holder);
nickjillings@1556 369 });
nickjillings@1556 370
nickjillings@1556 371
nickjillings@1556 372 testWaitIndicator();
nickjillings@1556 373 }
nickjillings@1556 374
nickjillings@1556 375 function sliderObject(audioObject) {
nickjillings@1556 376 // Create a new slider object;
nickjillings@1556 377 this.parent = audioObject;
nickjillings@1556 378 this.trackSliderObj = document.createElement('div');
nickjillings@1556 379 this.trackSliderObj.className = 'track-slider';
nickjillings@1556 380 this.trackSliderObj.id = 'track-slider-'+audioObject.id;
nickjillings@1556 381
nickjillings@1556 382 this.trackSliderObj.setAttribute('trackIndex',audioObject.id);
nickjillings@1556 383 this.trackSliderObj.innerHTML = '<span>'+audioObject.id+'</span>';
nickjillings@1556 384 this.trackSliderObj.draggable = true;
nickjillings@1556 385 this.trackSliderObj.ondragend = dragEnd;
nickjillings@1556 386
nickjillings@1556 387 // Onclick, switch playback to that track
nickjillings@1556 388 this.trackSliderObj.onclick = function() {
nickjillings@1556 389 // Start the test on first click, that way timings are more accurate.
nickjillings@1556 390 audioEngineContext.play();
nickjillings@1556 391 if (audioEngineContext.audioObjectsReady) {
nickjillings@1556 392 // Cannot continue to issue play command until audioObjects reported as ready!
nickjillings@1556 393 // Get the track ID from the object ID
nickjillings@1556 394 var element;
nickjillings@1556 395 if (event.srcElement.nodeName == "SPAN") {
nickjillings@1556 396 element = event.srcElement.parentNode;
nickjillings@1556 397 } else {
nickjillings@1556 398 element = event.srcElement;
nickjillings@1556 399 }
nickjillings@1556 400 var id = Number(element.attributes['trackIndex'].value);
nickjillings@1556 401 //audioEngineContext.metric.sliderPlayed(id);
nickjillings@1556 402 audioEngineContext.play(id);
nickjillings@1556 403 // Currently playing track red, rest green
nickjillings@1556 404
nickjillings@1556 405 //document.getElementById('track-slider-'+index).style.backgroundColor = "#FF0000";
nickjillings@1556 406 $('.track-slider').removeClass('track-slider-playing');
nickjillings@1556 407 $(element).addClass('track-slider-playing');
nickjillings@1556 408 $('.comment-div').removeClass('comment-box-playing');
nickjillings@1556 409 $('#comment-div-'+id).addClass('comment-box-playing');
nickjillings@1556 410 }
nickjillings@1556 411 };
nickjillings@1556 412
nickjillings@1561 413 this.exportXMLDOM = function(audioObject) {
nickjillings@1556 414 // Called by the audioObject holding this element. Must be present
nickjillings@1556 415 var node = document.createElement('value');
nickjillings@1556 416 node.textContent = convSliderPosToRate(this.trackSliderObj);
nickjillings@1556 417 return node;
nickjillings@1556 418 };
nickjillings@1561 419 this.getValue = function() {
nickjillings@1561 420 return convSliderPosToRate(this.trackSliderObj);
nickjillings@1562 421 };
nickjillings@1556 422 }
nickjillings@1556 423
nickjillings@1556 424 function dragEnd(ev) {
nickjillings@1556 425 // Function call when a div has been dropped
nickjillings@1556 426 var slider = document.getElementById('slider');
nickjillings@1556 427 var marginSize = Number(slider.attributes['marginsize'].value);
nickjillings@1556 428 var w = slider.style.width;
nickjillings@1556 429 w = Number(w.substr(0,w.length-2));
nickjillings@1556 430 var x = ev.x;
nickjillings@1556 431 if (x >= marginSize && x < w+marginSize) {
nickjillings@1556 432 this.style.left = (x)+'px';
nickjillings@1556 433 } else {
nickjillings@1556 434 if (x<marginSize) {
nickjillings@1556 435 this.style.left = marginSize+'px';
nickjillings@1556 436 } else {
nickjillings@1556 437 this.style.left = (w+marginSize) + 'px';
nickjillings@1556 438 }
nickjillings@1556 439 }
nickjillings@1556 440 var time = audioEngineContext.timer.getTestTime();
nickjillings@1556 441 var id = Number(ev.srcElement.getAttribute('trackindex'));
nickjillings@1556 442 audioEngineContext.audioObjects[id].metric.moved(time,convSliderPosToRate(ev.srcElement));
nickjillings@1556 443 }
nickjillings@1556 444
nickjillings@1556 445 function buttonSubmitClick() // TODO: Only when all songs have been played!
nickjillings@1556 446 {
nickjillings@1557 447 var checks = specification.commonInterface.options;
nickjillings@1557 448 var canContinue = true;
nickjillings@1561 449
nickjillings@1561 450 // Check that the anchor and reference objects are correctly placed
nickjillings@1561 451 var audioObjs = audioEngineContext.audioObjects;
nickjillings@1561 452 var audioHolder = testState.stateMap[testState.stateIndex];
nickjillings@1561 453 var anchorId = null;
nickjillings@1561 454 var referenceId = null;
nickjillings@1561 455 for (var i=0; i<audioObjs.length; i++) {
nickjillings@1561 456 if (audioObjs[i].specification.anchor == true && anchorId == null) {anchorId = i;}
nickjillings@1561 457 if (audioObjs[i].specification.reference == true && referenceId == null) {referenceId = i;}
nickjillings@1561 458 }
nickjillings@1561 459 if (anchorId != null) {
nickjillings@1561 460 if (audioObjs[anchorId].specification.marker != null) {
nickjillings@1561 461 if (audioObjs[anchorId].interfaceDOM.getValue() > audioObjs[anchorId].specification.marker)
nickjillings@1561 462 {
nickjillings@1561 463 // Anchor is not set below
nickjillings@1561 464 console.log('Anchor node not below marker value');
nickjillings@1561 465 alert('Please keep listening');
nickjillings@1561 466 return;
nickjillings@1561 467 }
nickjillings@1561 468 } else {
nickjillings@1561 469 // No marker value given, ensure it is the minimum value
nickjillings@1561 470 var anchorVal = audioObjs[anchorId].interfaceDOM.getValue();
nickjillings@1561 471 for (var i=0; i<audioObjs.length; i++) {
nickjillings@1561 472 if (i != anchorId) {
nickjillings@1561 473 if (anchorVal > audioObjs[i].interfaceDOM.getValue()) {
nickjillings@1561 474 // Anchor not the minimum
nickjillings@1561 475 console.log('No marker set, anchor node not the minimum');
nickjillings@1561 476 alert('Please keep listening');
nickjillings@1561 477 return;
nickjillings@1561 478 }
nickjillings@1561 479 }
nickjillings@1561 480 }
nickjillings@1561 481 }
nickjillings@1561 482 }
nickjillings@1561 483 if (referenceId != null) {
nickjillings@1561 484 if (audioObjs[referenceId].specification.marker != null) {
nickjillings@1561 485 if (audioObjs[referenceId].interfaceDOM.getValue() < audioObjs[referenceId].specification.marker)
nickjillings@1561 486 {
nickjillings@1561 487 // Anchor is not set below
nickjillings@1561 488 console.log('Reference node not above marker value');
nickjillings@1561 489 alert('Please keep listening');
nickjillings@1561 490 return;
nickjillings@1561 491 }
nickjillings@1561 492 } else {
nickjillings@1561 493 // No marker value given, ensure it is the minimum value
nickjillings@1561 494 var referenceVal = audioObjs[referenceId].interfaceDOM.getValue();
nickjillings@1561 495 for (var i=0; i<audioObjs.length; i++) {
nickjillings@1561 496 if (i != referenceId) {
nickjillings@1561 497 if (referenceVal > audioObjs[i].interfaceDOM.getValue()) {
nickjillings@1561 498 // Anchor not the minimum
nickjillings@1561 499 console.log('No marker set, reference node not the maximum');
nickjillings@1561 500 alert('Please keep listening');
nickjillings@1561 501 return;
nickjillings@1561 502 }
nickjillings@1561 503 }
nickjillings@1561 504 }
nickjillings@1561 505 }
nickjillings@1561 506 }
nickjillings@1561 507
nickjillings@1557 508 for (var i=0; i<checks.length; i++) {
nickjillings@1557 509 if (checks[i].type == 'check')
nickjillings@1557 510 {
nickjillings@1557 511 switch(checks[i].check) {
nickjillings@1557 512 case 'fragmentPlayed':
nickjillings@1557 513 // Check if all fragments have been played
nickjillings@1557 514 var checkState = interfaceContext.checkAllPlayed();
nickjillings@1557 515 if (checkState == false) {canContinue = false;}
nickjillings@1557 516 break;
nickjillings@1557 517 case 'fragmentFullPlayback':
nickjillings@1557 518 // Check all fragments have been played to their full length
nickjillings@1557 519 var checkState = interfaceContext.checkAllPlayed();
nickjillings@1557 520 if (checkState == false) {canContinue = false;}
nickjillings@1557 521 console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead');
nickjillings@1557 522 break;
nickjillings@1557 523 case 'fragmentMoved':
nickjillings@1557 524 // Check all fragment sliders have been moved.
nickjillings@1557 525 var checkState = interfaceContext.checkAllMoved();
nickjillings@1557 526 if (checkState == false) {canContinue = false;}
nickjillings@1557 527 break;
nickjillings@1557 528 case 'fragmentComments':
nickjillings@1557 529 // Check all fragment sliders have been moved.
nickjillings@1557 530 var checkState = interfaceContext.checkAllCommented();
nickjillings@1557 531 if (checkState == false) {canContinue = false;}
nickjillings@1557 532 break;
nickjillings@1557 533 }
nickjillings@1557 534
nickjillings@1557 535 }
nickjillings@1557 536 }
nickjillings@1557 537
nickjillings@1557 538 if (canContinue) {
nickjillings@1556 539 if (audioEngineContext.status == 1) {
nickjillings@1556 540 var playback = document.getElementById('playback-button');
nickjillings@1556 541 playback.click();
nickjillings@1556 542 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options
nickjillings@1556 543 } else
nickjillings@1556 544 {
nickjillings@1556 545 if (audioEngineContext.timer.testStarted == false)
nickjillings@1556 546 {
nickjillings@1556 547 alert('You have not started the test! Please press start to begin the test!');
nickjillings@1556 548 return;
nickjillings@1556 549 }
nickjillings@1556 550 }
nickjillings@1556 551 testState.advanceState();
nickjillings@1557 552 }
nickjillings@1556 553 }
nickjillings@1556 554
nickjillings@1556 555 function convSliderPosToRate(slider)
nickjillings@1556 556 {
nickjillings@1556 557 var w = document.getElementById('slider').style.width;
nickjillings@1556 558 var marginsize = Number(document.getElementById('slider').attributes['marginsize'].value);
nickjillings@1556 559 var maxPix = w.substr(0,w.length-2);
nickjillings@1556 560 var pix = slider.style.left;
nickjillings@1556 561 pix = pix.substr(0,pix.length-2);
nickjillings@1556 562 var rate = (pix-marginsize)/maxPix;
nickjillings@1556 563 return rate;
nickjillings@1556 564 }
nickjillings@1556 565
nickjillings@1556 566 function resizeWindow(event){
nickjillings@1556 567 // Function called when the window has been resized.
nickjillings@1556 568 // MANDATORY FUNCTION
nickjillings@1556 569
nickjillings@1556 570 // Store the slider marker values
nickjillings@1556 571 var holdValues = [];
nickjillings@1556 572 $(".track-slider").each(function(index,sliderObj){
nickjillings@1556 573 holdValues.push(convSliderPosToRate(index));
nickjillings@1556 574 });
nickjillings@1556 575
nickjillings@1556 576 var width = event.target.innerWidth;
nickjillings@1556 577 var canvas = document.getElementById('sliderCanvasHolder');
nickjillings@1556 578 var sliderDiv = canvas.children[0];
nickjillings@1556 579 var sliderScaleDiv = canvas.children[1];
nickjillings@1556 580 var marginsize = Number(sliderDiv.attributes['marginsize'].value);
nickjillings@1556 581 var w = (marginsize+8)*2;
nickjillings@1556 582 sliderDiv.style.width = width - w + 'px';
nickjillings@1556 583 var width = width - w;
nickjillings@1556 584 // Move sliders into new position
nickjillings@1556 585 $(".track-slider").each(function(index,sliderObj){
nickjillings@1556 586 var pos = holdValues[index];
nickjillings@1556 587 var pix = pos * width;
nickjillings@1556 588 sliderObj.style.left = pix+marginsize+'px';
nickjillings@1556 589 });
nickjillings@1556 590
nickjillings@1556 591 // Move scale labels
nickjillings@1556 592 $(sliderScaleDiv.children).each(function(index,scaleObj){
nickjillings@1556 593 var position = Number(scaleObj.attributes['value'].value);
nickjillings@1556 594 var pixelPosition = (position*width)+marginsize;
nickjillings@1556 595 scaleObj.style.left = Math.floor((pixelPosition-($(scaleObj).width()/2)))+'px';
nickjillings@1556 596 });
nickjillings@1556 597 }
nickjillings@1556 598
nickjillings@1556 599 function pageXMLSave(store, testXML)
nickjillings@1556 600 {
nickjillings@1556 601 // Saves a specific test page
nickjillings@1556 602 var xmlDoc = store;
nickjillings@1556 603 // Check if any session wide metrics are enabled
nickjillings@1556 604
nickjillings@1556 605 var commentShow = testXML.elementComments;
nickjillings@1556 606
nickjillings@1556 607 var metric = document.createElement('metric');
nickjillings@1556 608 if (audioEngineContext.metric.enableTestTimer)
nickjillings@1556 609 {
nickjillings@1556 610 var testTime = document.createElement('metricResult');
nickjillings@1556 611 testTime.id = 'testTime';
nickjillings@1556 612 testTime.textContent = audioEngineContext.timer.testDuration;
nickjillings@1556 613 metric.appendChild(testTime);
nickjillings@1556 614 }
nickjillings@1556 615 xmlDoc.appendChild(metric);
nickjillings@1556 616 var audioObjects = audioEngineContext.audioObjects;
nickjillings@1556 617 for (var i=0; i<audioObjects.length; i++)
nickjillings@1556 618 {
nickjillings@1556 619 var audioElement = audioEngineContext.audioObjects[i].exportXMLDOM();
nickjillings@1556 620 xmlDoc.appendChild(audioElement);
nickjillings@1556 621 }
nickjillings@1556 622
nickjillings@1556 623 $(interfaceContext.commentQuestions).each(function(index,element){
nickjillings@1556 624 var node = element.exportXMLDOM();
nickjillings@1556 625 xmlDoc.appendChild(node);
nickjillings@1556 626 });
nickjillings@1556 627 store = xmlDoc;
nickjillings@1556 628 }