annotate ape.js @ 693:a74cb47e779c

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