annotate ape.js @ 1578:e7546cabe1f3

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