annotate ape.js @ 16:f2dad7c64e1e

Added comments. Variable name changes to match specification document during ape.js loading.
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Tue, 07 Apr 2015 11:32:46 +0100
parents 94e080247b11
children a87846fba882 375410a5571d
rev   line source
nicholas@2 1 /**
nicholas@2 2 * ape.js
nicholas@2 3 * Create the APE interface
nicholas@2 4 */
nicholas@2 5
nicholas@2 6 // Once this is loaded and parsed, begin execution
nicholas@2 7 loadInterface(projectXML);
nicholas@2 8
nicholas@2 9 function loadInterface(xmlDoc) {
nicholas@2 10
n@16 11 // Get the dimensions of the screen available to the page
nicholas@2 12 var width = window.innerWidth;
nicholas@2 13 var height = window.innerHeight;
nicholas@2 14
nicholas@2 15 // Set background to grey #ddd
nicholas@2 16 document.getElementsByTagName('body')[0].style.backgroundColor = '#ddd';
nicholas@2 17
nicholas@2 18 // The injection point into the HTML page
nicholas@2 19 var insertPoint = document.getElementById("topLevelBody");
nicholas@2 20
nicholas@7 21
nicholas@2 22 // Decode parts of the xmlDoc that are needed
nicholas@2 23 // xmlDoc MUST already be parsed by jQuery!
nicholas@2 24 var xmlSetup = xmlDoc.find('setup');
nicholas@2 25 // Should put in an error function here incase of malprocessed or malformed XML
nicholas@2 26
nicholas@2 27 // Create the top div for the Title element
nicholas@2 28 var titleAttr = xmlSetup[0].attributes['title'];
nicholas@2 29 var title = document.createElement('div');
nicholas@2 30 title.className = "title";
nicholas@2 31 title.align = "center";
nicholas@2 32 var titleSpan = document.createElement('span');
nicholas@2 33
nicholas@2 34 // Set title to that defined in XML, else set to default
nicholas@2 35 if (titleAttr != undefined) {
nicholas@2 36 titleSpan.innerText = titleAttr.value;
nicholas@2 37 } else {
nicholas@2 38 titleSpan.innerText = 'APE Tool';
nicholas@2 39 }
nicholas@2 40 // Insert the titleSpan element into the title div element.
nicholas@2 41 title.appendChild(titleSpan);
nicholas@2 42
nicholas@7 43 // Store the return URL path in global projectReturn
nicholas@7 44 projectReturn = xmlSetup[0].attributes['projectReturn'].value;
nicholas@7 45
nicholas@7 46 // Create Interface buttons!
nicholas@7 47 var interfaceButtons = document.createElement('div');
nicholas@7 48 interfaceButtons.id = 'interface-buttons';
nicholas@7 49
nicholas@7 50 // MANUAL DOWNLOAD POINT
nicholas@7 51 // If project return is null, this MUST be specified as the location to create the download link
nicholas@7 52 var downloadPoint = document.createElement('div');
nicholas@7 53 downloadPoint.id = 'download-point';
nicholas@7 54
nicholas@7 55 // Create playback start/stop points
nicholas@7 56 var playback = document.createElement("button");
nicholas@7 57 playback.innerText = 'Start';
n@16 58 // onclick function. Check if it is playing or not, call the correct function in the
n@16 59 // audioEngine, change the button text to reflect the next state.
nicholas@7 60 playback.onclick = function() {
nicholas@7 61 if (audioEngineContext.status == 0) {
nicholas@7 62 audioEngineContext.play();
nicholas@7 63 this.innerText = 'Stop';
nicholas@7 64 } else {
nicholas@7 65 audioEngineContext.stop();
nicholas@7 66 this.innerText = 'Start';
nicholas@7 67 }
n@16 68 };
nicholas@7 69 // Create Submit (save) button
nicholas@7 70 var submit = document.createElement("button");
nicholas@7 71 submit.innerText = 'Submit';
nicholas@7 72 submit.onclick = function() {
n@15 73 // TODO: Update this for postTest tags
nicholas@7 74 createProjectSave(projectReturn)
n@16 75 };
n@16 76 // Append the interface buttons into the interfaceButtons object.
nicholas@7 77 interfaceButtons.appendChild(playback);
nicholas@7 78 interfaceButtons.appendChild(submit);
nicholas@7 79 interfaceButtons.appendChild(downloadPoint);
nicholas@7 80
nicholas@2 81 // Now create the slider and HTML5 canvas boxes
nicholas@2 82
n@16 83 // Create the div box to center align
nicholas@2 84 var sliderBox = document.createElement('div');
nicholas@2 85 sliderBox.className = 'sliderCanvasDiv';
n@16 86 sliderBox.id = 'sliderCanvasHolder';
nicholas@2 87 sliderBox.align = 'center';
nicholas@2 88
n@16 89 // Create the slider box to hold the slider elements
nicholas@5 90 var canvas = document.createElement('div');
nicholas@2 91 canvas.id = 'slider';
n@16 92 // Must have a known EXACT width, as this is used later to determine the ratings
nicholas@5 93 canvas.style.width = width - 100 +"px";
nicholas@5 94 canvas.style.height = 150 + "px";
n@16 95 canvas.style.marginBottom = "25px";
nicholas@2 96 canvas.style.backgroundColor = '#eee';
nicholas@5 97 canvas.align = "left";
nicholas@2 98 sliderBox.appendChild(canvas);
n@16 99
n@16 100 // Global parent for the comment boxes on the page
nicholas@3 101 var feedbackHolder = document.createElement('div');
n@16 102 // Find the parent audioHolder object.
n@16 103 var audioHolder = xmlDoc.find('audioHolder');
n@16 104 audioHolder = audioHolder[0]; // Remove from one field array
n@16 105 // Extract the hostURL attribute. If not set, create an empty string.
n@16 106 var hostURL = audioHolder.attributes['hostURL'];
nicholas@7 107 if (hostURL == undefined) {
nicholas@7 108 hostURL = "";
nicholas@7 109 } else {
nicholas@7 110 hostURL = hostURL.value;
nicholas@7 111 }
n@16 112 // Extract the sampleRate. If set, convert the string to a Number.
n@16 113 var hostFs = audioHolder.attributes['sampleRate'];
n@15 114 if (hostFs != undefined) {
n@15 115 hostFs = Number(hostFs.value);
nicholas@7 116 }
nicholas@7 117
nicholas@7 118 /// CHECK FOR SAMPLE RATE COMPATIBILITY
n@15 119 if (hostFs != undefined) {
nicholas@7 120 if (Number(hostFs) != audioContext.sampleRate) {
nicholas@7 121 var errStr = 'Sample rates do not match! Requested '+Number(hostFs)+', got '+audioContext.sampleRate+'. Please set the sample rate to match before completing this test.';
nicholas@7 122 alert(errStr);
nicholas@7 123 return;
nicholas@7 124 }
nicholas@7 125 }
n@16 126 // Find all the audioElements from the audioHolder
n@16 127 var audioElements = $(audioHolder).find('audioElements');
n@16 128 audioElements.each(function(index,element){
nicholas@7 129 // Find URL of track
n@16 130 // In this jQuery loop, variable 'this' holds the current audioElement.
n@16 131
n@16 132 // Now load each audio sample. First create the new track by passing the full URL
nicholas@7 133 var trackURL = hostURL + this.attributes['url'].value;
nicholas@7 134 audioEngineContext.newTrack(trackURL);
n@16 135 // Create document objects to hold the comment boxes
n@16 136 var trackComment = document.createElement('div');
n@16 137 // Create a string next to each comment asking for a comment
n@16 138 var trackString = document.createElement('span');
n@16 139 trackString.innerText = 'Comment on track '+index;
n@16 140 // Create the HTML5 comment box 'textarea'
n@16 141 var trackCommentBox = document.createElement('textarea');
n@16 142 trackCommentBox.rows = '4';
n@16 143 trackCommentBox.cols = '100';
n@16 144 trackCommentBox.name = 'trackComment'+index;
n@16 145 trackCommentBox.className = 'trackComment';
n@16 146 // Add to the holder.
n@16 147 trackComment.appendChild(trackString);
n@16 148 trackComment.appendChild(trackCommentBox);
n@16 149 feedbackHolder.appendChild(trackComment);
n@16 150
nicholas@5 151 // Create a slider per track
nicholas@5 152
nicholas@5 153 var trackSliderObj = document.createElement('div');
nicholas@5 154 trackSliderObj.className = 'track-slider';
nicholas@5 155 trackSliderObj.id = 'track-slider-'+index;
nicholas@5 156 trackSliderObj.style.position = 'absolute';
nicholas@5 157 // Distribute it randomnly
nicholas@5 158 var w = window.innerWidth - 100;
nicholas@5 159 w = Math.random()*w;
nicholas@5 160 trackSliderObj.style.left = Math.floor(w)+50+'px';
nicholas@5 161 trackSliderObj.style.height = "150px";
nicholas@5 162 trackSliderObj.style.width = "10px";
nicholas@5 163 trackSliderObj.style.backgroundColor = 'rgb(100,200,100)';
nicholas@5 164 trackSliderObj.innerHTML = '<span>'+index+'</span>';
nicholas@5 165 trackSliderObj.style.float = "left";
nicholas@5 166 trackSliderObj.draggable = true;
nicholas@5 167 trackSliderObj.ondragend = dragEnd;
nicholas@8 168
nicholas@8 169 // Onclick, switch playback to that track
nicholas@8 170 trackSliderObj.onclick = function() {
nicholas@8 171 // Get the track ID from the object ID
nicholas@8 172 var id = Number(this.id.substr(13,2)); // Maximum theoretical tracks is 99!
nicholas@8 173 audioEngineContext.selectedTrack(id);
n@15 174 };
nicholas@8 175
nicholas@5 176 canvas.appendChild(trackSliderObj);
n@15 177 });
nicholas@3 178
nicholas@2 179
nicholas@2 180 // Inject into HTML
nicholas@2 181 insertPoint.innerHTML = null; // Clear the current schema
nicholas@2 182 insertPoint.appendChild(title); // Insert the title
nicholas@7 183 insertPoint.appendChild(interfaceButtons);
nicholas@2 184 insertPoint.appendChild(sliderBox);
nicholas@3 185 insertPoint.appendChild(feedbackHolder);
nicholas@2 186 }
nicholas@5 187
nicholas@5 188 function dragEnd(ev) {
nicholas@5 189 // Function call when a div has been dropped
nicholas@5 190 if (ev.x >= 50 && ev.x < window.innerWidth-50) {
nicholas@5 191 this.style.left = (ev.x)+'px';
nicholas@5 192 } else {
nicholas@5 193 if (ev.x<50) {
nicholas@5 194 this.style.left = '50px';
nicholas@5 195 } else {
nicholas@5 196 this.style.left = window.innerWidth-50 + 'px';
nicholas@5 197 }
nicholas@5 198 }
nicholas@5 199 }
nicholas@7 200
nicholas@7 201 // Only other global function which must be defined in the interface class. Determines how to create the XML document.
nicholas@7 202 function interfaceXMLSave(){
nicholas@7 203 // Create the XML string to be exported with results
nicholas@7 204 var xmlDoc = document.createElement("BrowserEvaluationResult");
nicholas@7 205 var trackSliderObjects = document.getElementsByClassName('track-slider');
nicholas@7 206 var commentObjects = document.getElementsByClassName('trackComment');
nicholas@7 207 var rateMin = 50;
nicholas@7 208 var rateMax = window.innerWidth-50;
nicholas@7 209 for (var i=0; i<trackSliderObjects.length; i++)
nicholas@7 210 {
nicholas@7 211 var trackObj = document.createElement("Track");
nicholas@7 212 trackObj.id = i;
nicholas@7 213 var slider = document.createElement("Rating");
nicholas@7 214 var rate = Number(trackSliderObjects[i].style.left.substr(0,trackSliderObjects[i].style.left.length-2));
nicholas@7 215 rate = (rate-rateMin)/rateMax;
nicholas@7 216 slider.innerText = Math.floor(rate*100);
nicholas@7 217 var comment = document.createElement("Comment");
nicholas@7 218 comment.innerText = commentObjects[i].value;
nicholas@7 219 trackObj.appendChild(slider);
nicholas@7 220 trackObj.appendChild(comment);
nicholas@7 221 xmlDoc.appendChild(trackObj);
nicholas@7 222 }
nicholas@7 223
nicholas@7 224 return xmlDoc;
nicholas@7 225 }
nicholas@7 226