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