annotate interfaces/timeline.js @ 2480:713a2d059a16

Completed waveform/timeline interface. Need to add in checks
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Thu, 04 Aug 2016 11:34:29 +0100
parents dbe43b4ab7aa
children 3c92c732fb05
rev   line source
nicholas@2479 1 /**
nicholas@2479 2 * WAET Timeline
nicholas@2479 3 * This interface plots a waveform timeline per audio fragment on a page. Clicking on the fragment will generate a comment box for processing.
nicholas@2479 4 */
nicholas@2479 5
nicholas@2479 6 // Once this is loaded and parsed, begin execution
nicholas@2479 7 loadInterface();
nicholas@2479 8
nicholas@2479 9 function loadInterface() {
nicholas@2479 10 // Use this to do any one-time page / element construction. For instance, placing any stationary text objects,
nicholas@2479 11 // holding div's, or setting up any nodes which are present for the entire test sequence
nicholas@2479 12
nicholas@2479 13 interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema
nicholas@2479 14
nicholas@2479 15 interfaceContext.insertPoint = document.getElementById("topLevelBody");
nicholas@2479 16 var testContent = document.createElement("div");
nicholas@2479 17
nicholas@2479 18 // Create the top div and Title element
nicholas@2479 19 var title = document.createElement("div");
nicholas@2479 20 title.className = "title";
nicholas@2479 21 title.align = "center";
nicholas@2479 22 var titleSpan = document.createElement("span");
nicholas@2479 23 titleSpan.id = "test-title";
nicholas@2479 24 titleSpan.textContent = "Listening Test";
nicholas@2479 25 title.appendChild(titleSpan);
nicholas@2479 26
nicholas@2479 27 var pagetitle = document.createElement("div");
nicholas@2479 28 pagetitle.className = "pageTitle";
nicholas@2479 29 pagetitle.align = "center";
nicholas@2479 30 titleSpan = document.createElement("span");
nicholas@2479 31 titleSpan.id = "page-title";
nicholas@2479 32 pagetitle.appendChild(titleSpan);
nicholas@2479 33
nicholas@2479 34 // Create Interface buttons
nicholas@2479 35 var interfaceButtons = document.createElement("div");
nicholas@2479 36 interfaceButtons.id = 'interface-buttons';
nicholas@2479 37 interfaceButtons.style.height = "25px";
nicholas@2479 38
nicholas@2479 39 // Create playback start/stop points
nicholas@2479 40 var playback = document.createElement("button");
nicholas@2479 41 playback.innerHTML = "Stop";
nicholas@2479 42 playback.id = "playback-button";
nicholas@2479 43 playback.onclick = function() {
nicholas@2479 44 if (audioEngineContext.status == 1) {
nicholas@2479 45 audioEngineContext.stop();
nicholas@2479 46 this.innerHTML = "Stop";
nicholas@2479 47 var time = audioEngineContext.timer.getTestTime();
nicholas@2479 48 console.log("Stopped at "+time);
nicholas@2479 49 }
nicholas@2479 50 };
nicholas@2479 51 // Create Submit (save) button
nicholas@2479 52 var submit = document.createElement("button");
nicholas@2479 53 submit.innerHTML = 'Next';
nicholas@2479 54 submit.onclick = buttonSubmitClick;
nicholas@2479 55 submit.id = 'submit-button';
nicholas@2479 56 submit.style.float = 'left';
nicholas@2479 57 // Append the interface buttons into the interfaceButtons object.
nicholas@2479 58 interfaceButtons.appendChild(playback);
nicholas@2479 59 interfaceButtons.appendChild(submit);
nicholas@2479 60
nicholas@2479 61 // Create outside reference holder
nicholas@2479 62 var outsideRef = document.createElement("div");
nicholas@2479 63 outsideRef.id = "outside-reference-holder";
nicholas@2479 64
nicholas@2479 65 // Create content point
nicholas@2479 66 var content = document.createElement("div");
nicholas@2479 67 content.id = "timeline-test-content";
nicholas@2479 68
nicholas@2479 69 //Inject
nicholas@2479 70 testContent.appendChild(title);
nicholas@2479 71 testContent.appendChild(pagetitle);
nicholas@2479 72 testContent.appendChild(interfaceButtons);
nicholas@2479 73 testContent.appendChild(outsideRef);
nicholas@2479 74 testContent.appendChild(content);
nicholas@2479 75 interfaceContext.insertPoint.appendChild(testContent);
nicholas@2479 76
nicholas@2479 77 // Load the full interface
nicholas@2479 78 testState.initialise();
nicholas@2479 79 testState.advanceState();
nicholas@2479 80 };
nicholas@2479 81
nicholas@2479 82 function loadTest(page)
nicholas@2479 83 {
nicholas@2479 84 // Called each time a new test page is to be build. The page specification node is the only item passed in
nicholas@2479 85 var content = document.getElementById("timeline-test-content");
nicholas@2479 86 content.innerHTML = "";
nicholas@2479 87 var interfaceObj = page.interfaces;
nicholas@2479 88 if (interfaceObj.length > 1)
nicholas@2479 89 {
nicholas@2479 90 console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node");
nicholas@2479 91 }
nicholas@2479 92 interfaceObj = interfaceObj[0];
nicholas@2479 93
nicholas@2479 94 //Set the page title
nicholas@2479 95 if (typeof page.title == "string" && page.title.length > 0)
nicholas@2479 96 {
nicholas@2479 97 document.getElementById("test-title").textContent = page.title;
nicholas@2479 98 }
nicholas@2479 99
nicholas@2479 100 if (interfaceObj.title != null) {
nicholas@2479 101 document.getElementById("page-title").textContent = interfaceObj.title;
nicholas@2479 102 }
nicholas@2479 103
nicholas@2479 104 // Delete outside reference
nicholas@2479 105 var outsideReferenceHolder = document.getElementById("outside-reference-holder");
nicholas@2479 106 outsideReferenceHolder.innerHTML = "";
nicholas@2479 107
nicholas@2479 108 var commentBoxPrefix = "Comment on track";
nicholas@2479 109 if (interfaceObj.commentBoxPrefix != undefined) {
nicholas@2479 110 commentBoxPrefix = interfaceObj.commentBoxPrefix;
nicholas@2479 111 }
nicholas@2479 112
nicholas@2479 113 $(page.audioElements).each(function(index,element){
nicholas@2479 114 var audioObject = audioEngineContext.newTrack(element);
nicholas@2479 115 if (page.audioElements.type == 'outside-reference') {
nicholas@2479 116 var refNode = interfaceContext.outsideReferenceDOM(audioObject,index,outsideReferenceHolder);
nicholas@2479 117 audioObject.bindInterface(orNode);
nicholas@2479 118 } else {
nicholas@2479 119 switch(audioObject.specification.parent.label) {
nicholas@2479 120 case "none":
nicholas@2479 121 label = "";
nicholas@2479 122 break;
nicholas@2479 123 case "letter":
nicholas@2479 124 label = String.fromCharCode(97 + index);
nicholas@2479 125 break;
nicholas@2479 126 case "capital":
nicholas@2479 127 label = String.fromCharCode(65 + index);
nicholas@2479 128 break;
nicholas@2479 129 default:
nicholas@2479 130 label = ""+index;
nicholas@2479 131 break;
nicholas@2479 132 }
nicholas@2479 133 var node = new interfaceObject(audioObject,label);
nicholas@2479 134
nicholas@2479 135 content.appendChild(node.DOM);
nicholas@2479 136 audioObject.bindInterface(node);
nicholas@2479 137 }
nicholas@2479 138 });
nicholas@2479 139
nicholas@2479 140 resizeWindow();
nicholas@2479 141 }
nicholas@2479 142
nicholas@2479 143 function interfaceObject(audioObject,labelstr)
nicholas@2479 144 {
nicholas@2479 145 // Each audio object has a waveform guide and self-generated comments
nicholas@2479 146 this.parent = audioObject;
nicholas@2479 147 this.DOM = document.createElement("div");
nicholas@2479 148 this.DOM.className = "timeline-element";
nicholas@2479 149 this.DOM.id = audioObject.specification.id;
nicholas@2479 150
nicholas@2479 151 var root = document.createElement("div");
nicholas@2479 152 root.className = "timeline-element-content";
nicholas@2479 153 this.DOM.appendChild(root);
nicholas@2479 154
nicholas@2479 155 var label = document.createElement("div");
nicholas@2479 156 label.style.textAlign = "center";
nicholas@2479 157 var labelSpan = document.createElement("span");
nicholas@2479 158 labelSpan.textContent = "Fragment "+labelstr;
nicholas@2479 159 label.appendChild(labelSpan);
nicholas@2479 160 root.appendChild(label);
nicholas@2479 161
nicholas@2479 162 var canvasHolder = document.createElement("div");
nicholas@2479 163 canvasHolder.className = "timeline-element-canvas-holder";
nicholas@2479 164 var buttonHolder = document.createElement("div");
nicholas@2479 165 buttonHolder.className = "timeline-element-button-holder";
nicholas@2479 166 var commentHolder = document.createElement("div");
nicholas@2479 167 commentHolder.className = "timeline-element-comment-holder";
nicholas@2479 168
nicholas@2479 169 root.appendChild(canvasHolder);
nicholas@2479 170 root.appendChild(buttonHolder);
nicholas@2479 171 root.appendChild(commentHolder);
nicholas@2479 172
nicholas@2479 173 this.comments = {
nicholas@2479 174 parent: this,
nicholas@2479 175 list: [],
nicholas@2479 176 Comment: function(parent,time, str) {
nicholas@2479 177 this.parent = parent;
nicholas@2479 178 this.time = time;
nicholas@2479 179 this.DOM = document.createElement("div");
nicholas@2480 180 this.DOM.className = "comment-entry";
nicholas@2480 181 var titleHolder = document.createElement("div");
nicholas@2480 182 titleHolder.className = "comment-entry-header";
nicholas@2479 183 this.title = document.createElement("span");
nicholas@2479 184 if (str != undefined) {
nicholas@2479 185 this.title.textContent = str;
nicholas@2479 186 } else {
nicholas@2479 187 this.title.textContent = "Time: "+time.toFixed(2)+"s";
nicholas@2479 188 }
nicholas@2480 189 titleHolder.appendChild(this.title);
nicholas@2479 190 this.textarea = document.createElement("textarea");
nicholas@2480 191 this.textarea.className = "comment-entry-text";
nicholas@2480 192 this.DOM.appendChild(titleHolder);
nicholas@2479 193 this.DOM.appendChild(this.textarea);
nicholas@2480 194
nicholas@2480 195 this.clear = {
nicholas@2480 196 DOM: document.createElement("button"),
nicholas@2480 197 parent: this,
nicholas@2480 198 handleEvent: function() {
nicholas@2480 199 this.parent.parent.deleteComment(this.parent);
nicholas@2480 200 }
nicholas@2480 201 }
nicholas@2480 202 this.clear.DOM.textContent = "Delete";
nicholas@2480 203 this.clear.DOM.addEventListener("click",this.clear);
nicholas@2480 204 titleHolder.appendChild(this.clear.DOM);
nicholas@2480 205
nicholas@2479 206 this.resize = function() {
nicholas@2479 207 var w = window.innerWidth;
nicholas@2479 208 w = Math.min(w,800);
nicholas@2479 209 w = Math.max(w,200);
nicholas@2479 210 var elem_w = w / 2.5;
nicholas@2479 211 elem_w = Math.max(elem_w,190);
nicholas@2479 212 this.DOM.style.width = elem_w+"px";
nicholas@2479 213 this.textarea.style.width = (elem_w-5)+"px";
nicholas@2479 214 }
nicholas@2480 215 this.buildXML = function(root) {
nicholas@2480 216 //storage.document.createElement();
nicholas@2480 217 var node = storage.document.createElement("comment");
nicholas@2480 218 var question = storage.document.createElement("question");
nicholas@2480 219 var comment = storage.document.createElement("response");
nicholas@2480 220 node.setAttribute("time",this.time);
nicholas@2480 221 question.textContent = this.title.textContent;
nicholas@2480 222 comment.textContent = this.textarea.value;
nicholas@2480 223 node.appendChild(question);
nicholas@2480 224 node.appendChild(comment);
nicholas@2480 225 root.appendChild(node);
nicholas@2480 226 }
nicholas@2479 227 this.resize();
nicholas@2479 228 },
nicholas@2479 229 newComment: function(time) {
nicholas@2479 230 var node = new this.Comment(this,time);
nicholas@2479 231 this.list.push(node);
nicholas@2479 232 commentHolder.appendChild(node.DOM);
nicholas@2479 233 return node;
nicholas@2479 234 },
nicholas@2479 235 deleteComment: function(comment) {
nicholas@2480 236 var index = this.list.findIndex(function(element,index,array){
nicholas@2480 237 if (element == comment) {return true;} return false;
nicholas@2480 238 },comment);
nicholas@2480 239 if (index == -1) {
nicholas@2480 240 return false;
nicholas@2480 241 }
nicholas@2480 242 var node = this.list.splice(index,1);
nicholas@2480 243 comment.DOM.remove();
nicholas@2480 244 this.parent.canvas.drawMarkers();
nicholas@2480 245 return true;
nicholas@2479 246 },
nicholas@2479 247 clearList: function() {
nicholas@2480 248 while(this.list.length > 0) {
nicholas@2480 249 this.deleteComment(this.list[0]);
nicholas@2480 250 }
nicholas@2479 251 }
nicholas@2479 252 }
nicholas@2479 253
nicholas@2479 254 this.canvas = {
nicholas@2479 255 parent: this,
nicholas@2479 256 comments: this.comments,
nicholas@2479 257 layer1: document.createElement("canvas"),
nicholas@2479 258 layer2: document.createElement("canvas"),
nicholas@2479 259 layer3: document.createElement("canvas"),
nicholas@2479 260 layer4: document.createElement("canvas"),
nicholas@2479 261 resize: function(w) {
nicholas@2479 262 this.layer1.width = w;
nicholas@2479 263 this.layer2.width = w;
nicholas@2479 264 this.layer3.width = w;
nicholas@2479 265 this.layer4.width = w;
nicholas@2479 266 this.layer1.style.width = w+"px";
nicholas@2479 267 this.layer2.style.width = w+"px";
nicholas@2479 268 this.layer3.style.width = w+"px";
nicholas@2479 269 this.layer4.style.width = w+"px";
nicholas@2480 270 this.drawWaveform();
nicholas@2480 271 this.drawMarkers();
nicholas@2479 272 },
nicholas@2479 273 handleEvent: function(event) {
nicholas@2479 274 switch(event.currentTarget) {
nicholas@2479 275 case this.layer1:
nicholas@2479 276 switch(event.type) {
nicholas@2479 277 case "mousemove":
nicholas@2479 278 this.drawMouse(event);
nicholas@2479 279 break;
nicholas@2479 280 case "mouseleave":
nicholas@2479 281 this.clearCanvas(this.layer1);
nicholas@2479 282 break;
nicholas@2479 283 case "click":
nicholas@2479 284 var rect = this.layer1.getBoundingClientRect();
nicholas@2479 285 var pixX = event.clientX - rect.left;
nicholas@2479 286 var tpp = this.parent.parent.buffer.buffer.duration/this.layer1.width;
nicholas@2479 287 this.comments.newComment(pixX*tpp);
nicholas@2479 288 this.drawMarkers();
nicholas@2479 289 break;
nicholas@2479 290 }
nicholas@2479 291 break;
nicholas@2479 292 }
nicholas@2479 293 },
nicholas@2479 294 drawWaveform: function() {
nicholas@2480 295 if (this.parent.parent == undefined || this.parent.parent.buffer == undefined) {
nicholas@2480 296 return;
nicholas@2480 297 }
nicholas@2479 298 var buffer = this.parent.parent.buffer.buffer;
nicholas@2479 299 var context = this.layer4.getContext("2d");
nicholas@2479 300 context.lineWidth = 1;
nicholas@2479 301 context.strokeStyle = "#888";
nicholas@2479 302 context.clearRect(0,0,this.layer4.width, this.layer4.height);
nicholas@2479 303 var data = buffer.getChannelData(0);
nicholas@2479 304 var t_per_pixel = buffer.duration/this.layer4.width;
nicholas@2479 305 var s_per_pixel = data.length/this.layer4.width;
nicholas@2479 306 var pixX = 0;
nicholas@2479 307 while (pixX < this.layer4.width) {
nicholas@2479 308 var start = Math.floor(s_per_pixel*pixX);
nicholas@2479 309 var end = Math.min(Math.ceil(s_per_pixel*(pixX+1)),data.length);
nicholas@2479 310 var frame = data.subarray(start,end);
nicholas@2479 311 var min = frame[0];
nicholas@2479 312 var max = min;
nicholas@2479 313 for (var n=0; n<frame.length; n++) {
nicholas@2479 314 if (frame[n] < min) {min = frame[n];}
nicholas@2479 315 if (frame[n] > max) {max = frame[n];}
nicholas@2479 316 }
nicholas@2479 317 // Assuming min/max normalised between [-1, 1] to map to [150, 0]
nicholas@2479 318 context.beginPath();
nicholas@2479 319 context.moveTo(pixX+0.5,(min+1)*-75+150);
nicholas@2479 320 context.lineTo(pixX+0.5,(max+1)*-75+150);
nicholas@2479 321 context.stroke();
nicholas@2479 322 pixX++;
nicholas@2479 323 }
nicholas@2479 324 },
nicholas@2479 325 drawMouse: function(event) {
nicholas@2479 326 var context = this.layer1.getContext("2d");
nicholas@2479 327 context.clearRect(0,0,this.layer1.width, this.layer1.height);
nicholas@2479 328 var rect = this.layer1.getBoundingClientRect();
nicholas@2479 329 var pixX = event.clientX - rect.left;
nicholas@2479 330 pixX = Math.floor(pixX)-0.5;
nicholas@2479 331 context.strokeStyle = "#800";
nicholas@2479 332 context.beginPath();
nicholas@2479 333 context.moveTo(pixX,0);
nicholas@2479 334 context.lineTo(pixX,this.layer1.height);
nicholas@2479 335 context.stroke();
nicholas@2479 336 },
nicholas@2479 337 drawTicker: function() {
nicholas@2479 338 var context = this.layer2.getContext("2d");
nicholas@2479 339 context.clearRect(0,0,this.layer2.width, this.layer2.height);
nicholas@2479 340 var time = this.parent.parent.getCurrentPosition();
nicholas@2479 341 var ratio = time / this.parent.parent.buffer.buffer.duration;
nicholas@2479 342 var pixX = Math.floor(ratio*this.layer2.width)+0.5;
nicholas@2479 343 context.strokeStyle = "#080";
nicholas@2479 344 context.beginPath();
nicholas@2479 345 context.moveTo(pixX,0);
nicholas@2479 346 context.lineTo(pixX,this.layer2.height);
nicholas@2479 347 context.stroke();
nicholas@2479 348 },
nicholas@2479 349 drawMarkers: function() {
nicholas@2480 350 if (this.parent.parent == undefined || this.parent.parent.buffer == undefined) {
nicholas@2480 351 return;
nicholas@2480 352 }
nicholas@2479 353 var context = this.layer3.getContext("2d");
nicholas@2479 354 context.clearRect(0,0,this.layer3.width, this.layer3.height);
nicholas@2479 355 context.strokeStyle = "#008";
nicholas@2479 356 var tpp = this.parent.parent.buffer.buffer.duration/this.layer1.width;
nicholas@2479 357 for (var i=0; i<this.comments.list.length; i++) {
nicholas@2479 358 var comment = this.comments.list[i];
nicholas@2479 359 var pixX = Math.floor(comment.time/tpp)+0.5;
nicholas@2479 360 context.beginPath();
nicholas@2479 361 context.moveTo(pixX,0);
nicholas@2479 362 context.lineTo(pixX,this.layer3.height);
nicholas@2479 363 context.stroke();
nicholas@2479 364 }
nicholas@2479 365 },
nicholas@2479 366 clearCanvas: function(canvas) {
nicholas@2479 367 var context = canvas.getContext("2d");
nicholas@2479 368 context.clearRect(0,0,canvas.width, canvas.height);
nicholas@2479 369 }
nicholas@2479 370 }
nicholas@2479 371 this.canvas.layer1.className = "timeline-element-canvas canvas-layer1 canvas-disabled";
nicholas@2479 372 this.canvas.layer2.className = "timeline-element-canvas canvas-layer2";
nicholas@2479 373 this.canvas.layer3.className = "timeline-element-canvas canvas-layer3";
nicholas@2479 374 this.canvas.layer4.className = "timeline-element-canvas canvas-layer3";
nicholas@2479 375 this.canvas.layer1.height = "150";
nicholas@2479 376 this.canvas.layer2.height = "150";
nicholas@2479 377 this.canvas.layer3.height = "150";
nicholas@2479 378 this.canvas.layer4.height = "150";
nicholas@2479 379 canvasHolder.appendChild(this.canvas.layer1);
nicholas@2479 380 canvasHolder.appendChild(this.canvas.layer2);
nicholas@2479 381 canvasHolder.appendChild(this.canvas.layer3);
nicholas@2479 382 canvasHolder.appendChild(this.canvas.layer4);
nicholas@2479 383 this.canvas.layer1.addEventListener("mousemove",this.canvas);
nicholas@2479 384 this.canvas.layer1.addEventListener("mouseleave",this.canvas);
nicholas@2479 385 this.canvas.layer1.addEventListener("click",this.canvas);
nicholas@2479 386
nicholas@2479 387 var canvasIntervalID = null;
nicholas@2479 388
nicholas@2479 389 this.playButton = {
nicholas@2479 390 parent: this,
nicholas@2479 391 DOM: document.createElement("button"),
nicholas@2479 392 handleEvent: function(event) {
nicholas@2479 393 var id = this.parent.parent.id;
nicholas@2479 394 var str = this.DOM.textContent;
nicholas@2479 395 if (str == "Play") {
nicholas@2479 396 audioEngineContext.play(id);
nicholas@2479 397 } else if (str == "Stop") {
nicholas@2479 398 audioEngineContext.stop();
nicholas@2479 399 }
nicholas@2479 400 }
nicholas@2479 401 }
nicholas@2479 402 this.playButton.DOM.addEventListener("click",this.playButton);
nicholas@2479 403 this.playButton.DOM.className = "timeline-button timeline-button-disabled";
nicholas@2479 404 this.playButton.DOM.disabled = true;
nicholas@2479 405 this.playButton.DOM.textContent = "Wait";
nicholas@2479 406
nicholas@2479 407 buttonHolder.appendChild(this.playButton.DOM);
nicholas@2479 408
nicholas@2479 409 this.resize = function() {
nicholas@2479 410 var w = window.innerWidth;
nicholas@2479 411 w = Math.min(w,800);
nicholas@2479 412 w = Math.max(w,200);
nicholas@2479 413 root.style.width = w+"px";
nicholas@2479 414 var c_w = w-100;
nicholas@2479 415 this.canvas.resize(c_w);
nicholas@2479 416 }
nicholas@2479 417
nicholas@2479 418 this.enable = function()
nicholas@2479 419 {
nicholas@2479 420 // This is used to tell the interface object that playback of this node is ready
nicholas@2479 421 this.canvas.layer1.addEventListener("click",this.canvas);
nicholas@2479 422 this.canvas.layer1.className = "timeline-element-canvas canvas-layer1";
nicholas@2479 423 this.playButton.DOM.className = "timeline-button timeline-button-play";
nicholas@2479 424 this.playButton.DOM.textContent = "Play";
nicholas@2479 425 this.playButton.DOM.disabled = false;
nicholas@2479 426
nicholas@2479 427 this.canvas.drawWaveform();
nicholas@2479 428 };
nicholas@2479 429 this.updateLoading = function(progress)
nicholas@2479 430 {
nicholas@2479 431 // progress is a value from 0 to 100 indicating the current download state of media files
nicholas@2479 432 progress = String(progress);
nicholas@2479 433 progress = progress.substr(0,5);
nicholas@2479 434 this.playButton.DOM.textContent = "Loading: "+progress+'%';
nicholas@2479 435 };
nicholas@2479 436 this.startPlayback = function()
nicholas@2479 437 {
nicholas@2479 438 // Called when playback has begun
nicholas@2479 439 canvasIntervalID = window.setInterval(this.canvas.drawTicker.bind(this.canvas),100);
nicholas@2479 440 this.playButton.DOM.textContent = "Stop";
nicholas@2479 441 };
nicholas@2479 442 this.stopPlayback = function()
nicholas@2479 443 {
nicholas@2479 444 // Called when playback has stopped. This gets called even if playback never started!
nicholas@2479 445 window.clearInterval(canvasIntervalID);
nicholas@2479 446 this.canvas.clearCanvas(this.canvas.layer2);
nicholas@2479 447 this.playButton.DOM.textContent = "Play";
nicholas@2479 448 };
nicholas@2479 449 this.getValue = function()
nicholas@2479 450 {
nicholas@2479 451 // Return the current value of the object. If there is no value, return 0
nicholas@2479 452 return 0;
nicholas@2479 453 };
nicholas@2479 454 this.getPresentedId = function()
nicholas@2479 455 {
nicholas@2479 456 // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale
nicholas@2479 457 return labelSpan.textContent;
nicholas@2479 458 };
nicholas@2479 459 this.canMove = function()
nicholas@2479 460 {
nicholas@2479 461 // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale.
nicholas@2479 462 // These are checked primarily if the interface check option 'fragmentMoved' is enabled.
nicholas@2479 463 return false;
nicholas@2479 464 };
nicholas@2479 465 this.exportXMLDOM = function(audioObject) {
nicholas@2479 466 // Called by the audioObject holding this element to export the interface <value> node.
nicholas@2479 467 // If there is no value node (such as outside reference), return null
nicholas@2479 468 // If there are multiple value nodes (such as multiple scale / 2D scales), return an array of nodes with each value node having an 'interfaceName' attribute
nicholas@2479 469 // Use storage.document.createElement('value'); to generate the XML node.
nicholas@2479 470 return null;
nicholas@2479 471 };
nicholas@2479 472 this.error = function() {
nicholas@2479 473 // If there is an error with the audioObject, this will be called to indicate a failure
nicholas@2479 474 }
nicholas@2479 475 };
nicholas@2479 476
nicholas@2479 477 function resizeWindow(event)
nicholas@2479 478 {
nicholas@2479 479 // Called on every window resize event, use this to scale your page properly
nicholas@2479 480 for (var i=0; i<audioEngineContext.audioObjects.length; i++) {
nicholas@2479 481 audioEngineContext.audioObjects[i].interfaceDOM.resize();
nicholas@2479 482 }
nicholas@2479 483 }
nicholas@2479 484
nicholas@2479 485 function buttonSubmitClick()
nicholas@2479 486 {
nicholas@2480 487 testState.advanceState();
nicholas@2479 488 }
nicholas@2479 489
nicholas@2479 490 function pageXMLSave(store, pageSpecification)
nicholas@2479 491 {
nicholas@2479 492 // MANDATORY
nicholas@2479 493 // Saves a specific test page
nicholas@2479 494 // You can use this space to add any extra nodes to your XML <audioHolder> saves
nicholas@2479 495 // Get the current <page> information in store (remember to appendChild your data to it)
nicholas@2479 496 // pageSpecification is the current page node configuration
nicholas@2479 497 // To create new XML nodes, use storage.document.createElement();
nicholas@2480 498
nicholas@2480 499 for (var i=0; i<audioEngineContext.audioObjects.length; i++) {
nicholas@2480 500 var id = audioEngineContext.audioObjects[i].specification.id;
nicholas@2480 501 var commentsList = audioEngineContext.audioObjects[i].interfaceDOM.comments.list;
nicholas@2480 502 var root = audioEngineContext.audioObjects[i].storeDOM;
nicholas@2480 503 for (var j=0; j<commentsList.length; j++) {
nicholas@2480 504 commentsList[j].buildXML(root);
nicholas@2480 505 }
nicholas@2480 506 }
nicholas@2479 507 }