annotate ape.js @ 1483:d99c580e2683

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