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