comparison interfaces/horizontal-sliders.js @ 2538:464c6c6692d6

Beautified entire project.
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Mon, 14 Nov 2016 14:17:03 +0000
parents 1647bb807186
children 342ef7948c47
comparison
equal deleted inserted replaced
2536:527020a63203 2538:464c6c6692d6
1 // Once this is loaded and parsed, begin execution 1 // Once this is loaded and parsed, begin execution
2 loadInterface(); 2 loadInterface();
3 3
4 function loadInterface() { 4 function loadInterface() {
5 // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, 5 // Use this to do any one-time page / element construction. For instance, placing any stationary text objects,
6 // holding div's, or setting up any nodes which are present for the entire test sequence 6 // holding div's, or setting up any nodes which are present for the entire test sequence
7 7
8 // The injection point into the HTML page 8 // The injection point into the HTML page
9 interfaceContext.insertPoint = document.getElementById("topLevelBody"); 9 interfaceContext.insertPoint = document.getElementById("topLevelBody");
10 var testContent = document.createElement('div'); 10 var testContent = document.createElement('div');
11 testContent.id = 'testContent'; 11 testContent.id = 'testContent';
12 12
13 // Create the top div for the Title element 13 // Create the top div for the Title element
14 var titleAttr = specification.title; 14 var titleAttr = specification.title;
15 var title = document.createElement('div'); 15 var title = document.createElement('div');
16 title.className = "title"; 16 title.className = "title";
17 title.align = "center"; 17 title.align = "center";
18 var titleSpan = document.createElement('span'); 18 var titleSpan = document.createElement('span');
19 titleSpan.id="test-title"; 19 titleSpan.id = "test-title";
20 20
21 // Set title to that defined in XML, else set to default 21 // Set title to that defined in XML, else set to default
22 if (titleAttr != undefined) { 22 if (titleAttr != undefined) {
23 titleSpan.textContent = titleAttr; 23 titleSpan.textContent = titleAttr;
24 } else { 24 } else {
25 titleSpan.textContent = 'Listening test'; 25 titleSpan.textContent = 'Listening test';
26 } 26 }
27 // Insert the titleSpan element into the title div element. 27 // Insert the titleSpan element into the title div element.
28 title.appendChild(titleSpan); 28 title.appendChild(titleSpan);
29 29
30 var pagetitle = document.createElement('div'); 30 var pagetitle = document.createElement('div');
31 pagetitle.className = "pageTitle"; 31 pagetitle.className = "pageTitle";
32 pagetitle.align = "center"; 32 pagetitle.align = "center";
33 var titleSpan = document.createElement('span'); 33 var titleSpan = document.createElement('span');
34 titleSpan.id = "pageTitle"; 34 titleSpan.id = "pageTitle";
35 pagetitle.appendChild(titleSpan); 35 pagetitle.appendChild(titleSpan);
36 36
37 // Create Interface buttons! 37 // Create Interface buttons!
38 var interfaceButtons = document.createElement('div'); 38 var interfaceButtons = document.createElement('div');
39 interfaceButtons.id = 'interface-buttons'; 39 interfaceButtons.id = 'interface-buttons';
40 interfaceButtons.style.height = '25px'; 40 interfaceButtons.style.height = '25px';
41 41
42 // Create playback start/stop points 42 // Create playback start/stop points
43 var playback = document.createElement("button"); 43 var playback = document.createElement("button");
44 playback.innerHTML = 'Stop'; 44 playback.innerHTML = 'Stop';
45 playback.id = 'playback-button'; 45 playback.id = 'playback-button';
46 playback.style.float = 'left'; 46 playback.style.float = 'left';
47 // onclick function. Check if it is playing or not, call the correct function in the 47 // onclick function. Check if it is playing or not, call the correct function in the
48 // audioEngine, change the button text to reflect the next state. 48 // audioEngine, change the button text to reflect the next state.
49 playback.onclick = function() { 49 playback.onclick = function () {
50 if (audioEngineContext.status == 1) { 50 if (audioEngineContext.status == 1) {
51 audioEngineContext.stop(); 51 audioEngineContext.stop();
52 this.innerHTML = 'Stop'; 52 this.innerHTML = 'Stop';
53 var time = audioEngineContext.timer.getTestTime(); 53 var time = audioEngineContext.timer.getTestTime();
54 console.log('Stopped at ' + time); // DEBUG/SAFETY 54 console.log('Stopped at ' + time); // DEBUG/SAFETY
55 } 55 }
56 }; 56 };
57 // Create Submit (save) button 57 // Create Submit (save) button
58 var submit = document.createElement("button"); 58 var submit = document.createElement("button");
59 submit.innerHTML = 'Next'; 59 submit.innerHTML = 'Next';
60 submit.onclick = buttonSubmitClick; 60 submit.onclick = buttonSubmitClick;
61 submit.id = 'submit-button'; 61 submit.id = 'submit-button';
62 submit.style.float = 'left'; 62 submit.style.float = 'left';
63 // Append the interface buttons into the interfaceButtons object. 63 // Append the interface buttons into the interfaceButtons object.
64 interfaceButtons.appendChild(playback); 64 interfaceButtons.appendChild(playback);
65 interfaceButtons.appendChild(submit); 65 interfaceButtons.appendChild(submit);
66 66
67 // Create outside reference holder 67 // Create outside reference holder
68 var outsideRef = document.createElement("div"); 68 var outsideRef = document.createElement("div");
69 outsideRef.id = "outside-reference-holder"; 69 outsideRef.id = "outside-reference-holder";
70 70
71 // Create a slider box 71 // Create a slider box
72 var sliderBox = document.createElement('div'); 72 var sliderBox = document.createElement('div');
73 sliderBox.style.width = "100%"; 73 sliderBox.style.width = "100%";
74 sliderBox.style.height = window.innerHeight - 200+12 + 'px'; 74 sliderBox.style.height = window.innerHeight - 200 + 12 + 'px';
75 sliderBox.style.marginBottom = '10px'; 75 sliderBox.style.marginBottom = '10px';
76 sliderBox.id = 'slider'; 76 sliderBox.id = 'slider';
77 var scaleHolder = document.createElement('div'); 77 var scaleHolder = document.createElement('div');
78 scaleHolder.id = "scale-holder"; 78 scaleHolder.id = "scale-holder";
79 scaleHolder.style.marginLeft = "107px"; 79 scaleHolder.style.marginLeft = "107px";
80 sliderBox.appendChild(scaleHolder); 80 sliderBox.appendChild(scaleHolder);
81 var scaleText = document.createElement('div'); 81 var scaleText = document.createElement('div');
82 scaleText.id = "scale-text-holder"; 82 scaleText.id = "scale-text-holder";
83 scaleText.style.height = "25px"; 83 scaleText.style.height = "25px";
84 scaleText.style.width = "100%"; 84 scaleText.style.width = "100%";
85 scaleHolder.appendChild(scaleText); 85 scaleHolder.appendChild(scaleText);
86 var scaleCanvas = document.createElement('canvas'); 86 var scaleCanvas = document.createElement('canvas');
87 scaleCanvas.id = "scale-canvas"; 87 scaleCanvas.id = "scale-canvas";
88 scaleCanvas.style.marginLeft = "100px"; 88 scaleCanvas.style.marginLeft = "100px";
89 scaleHolder.appendChild(scaleCanvas); 89 scaleHolder.appendChild(scaleCanvas);
90 var sliderObjectHolder = document.createElement('div'); 90 var sliderObjectHolder = document.createElement('div');
91 sliderObjectHolder.id = 'slider-holder'; 91 sliderObjectHolder.id = 'slider-holder';
92 sliderObjectHolder.align = "center"; 92 sliderObjectHolder.align = "center";
93 sliderBox.appendChild(sliderObjectHolder); 93 sliderBox.appendChild(sliderObjectHolder);
94 94
95 // Global parent for the comment boxes on the page 95 // Global parent for the comment boxes on the page
96 var feedbackHolder = document.createElement('div'); 96 var feedbackHolder = document.createElement('div');
97 feedbackHolder.id = 'feedbackHolder'; 97 feedbackHolder.id = 'feedbackHolder';
98 98
99 testContent.style.zIndex = 1; 99 testContent.style.zIndex = 1;
100 interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema 100 interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema
101 101
102 // Inject into HTML 102 // Inject into HTML
103 testContent.appendChild(title); // Insert the title 103 testContent.appendChild(title); // Insert the title
104 testContent.appendChild(pagetitle); 104 testContent.appendChild(pagetitle);
105 testContent.appendChild(interfaceButtons); 105 testContent.appendChild(interfaceButtons);
106 testContent.appendChild(outsideRef); 106 testContent.appendChild(outsideRef);
107 testContent.appendChild(sliderBox); 107 testContent.appendChild(sliderBox);
108 testContent.appendChild(feedbackHolder); 108 testContent.appendChild(feedbackHolder);
109 interfaceContext.insertPoint.appendChild(testContent); 109 interfaceContext.insertPoint.appendChild(testContent);
110 110
111 // Load the full interface 111 // Load the full interface
112 testState.initialise(); 112 testState.initialise();
113 testState.advanceState(); 113 testState.advanceState();
114 }; 114 };
115 115
116 function loadTest(page) 116 function loadTest(page) {
117 { 117 // Called each time a new test page is to be build. The page specification node is the only item passed in
118 // Called each time a new test page is to be build. The page specification node is the only item passed in 118 var id = page.id;
119 var id = page.id; 119
120 120 var feedbackHolder = document.getElementById('feedbackHolder');
121 var feedbackHolder = document.getElementById('feedbackHolder');
122 feedbackHolder.innerHTML = ""; 121 feedbackHolder.innerHTML = "";
123 122
124 var interfaceObj = page.interfaces; 123 var interfaceObj = page.interfaces;
125 if (interfaceObj.length > 1) 124 if (interfaceObj.length > 1) {
126 { 125 console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node");
127 console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); 126 }
128 } 127 interfaceObj = interfaceObj[0];
129 interfaceObj = interfaceObj[0]; 128
130
131 // Set the page title 129 // Set the page title
132 if (typeof page.title == "string" && page.title.length > 0) { 130 if (typeof page.title == "string" && page.title.length > 0) {
133 document.getElementById("test-title").textContent = page.title 131 document.getElementById("test-title").textContent = page.title
134 } 132 }
135 133
136 if(interfaceObj.title != null) 134 if (interfaceObj.title != null) {
137 { 135 document.getElementById("pageTitle").textContent = interfaceObj.title;
138 document.getElementById("pageTitle").textContent = interfaceObj.title; 136 }
139 } 137
140 138 // Delete outside reference
141 // Delete outside reference 139 document.getElementById("outside-reference-holder").innerHTML = "";
142 document.getElementById("outside-reference-holder").innerHTML = ""; 140
143 141 var sliderBox = document.getElementById('slider-holder');
144 var sliderBox = document.getElementById('slider-holder'); 142 sliderBox.innerHTML = "";
145 sliderBox.innerHTML = ""; 143
146 144 var commentBoxPrefix = "Comment on track";
147 var commentBoxPrefix = "Comment on track"; 145 if (interfaceObj.commentBoxPrefix != undefined) {
148 if (interfaceObj.commentBoxPrefix != undefined) { 146 commentBoxPrefix = interfaceObj.commentBoxPrefix;
149 commentBoxPrefix = interfaceObj.commentBoxPrefix; 147 }
150 } 148 var loopPlayback = page.loop;
151 var loopPlayback = page.loop; 149
152 150 $(page.commentQuestions).each(function (index, element) {
153 $(page.commentQuestions).each(function(index,element) { 151 var node = interfaceContext.createCommentQuestion(element);
154 var node = interfaceContext.createCommentQuestion(element); 152 feedbackHolder.appendChild(node.holder);
155 feedbackHolder.appendChild(node.holder); 153 });
156 }); 154
157 155 // Find all the audioElements from the audioHolder
158 // Find all the audioElements from the audioHolder 156 var index = 0;
159 var index = 0; 157 $(page.audioElements).each(function (index, element) {
160 $(page.audioElements).each(function(index,element){ 158 // Find URL of track
161 // Find URL of track 159 // In this jQuery loop, variable 'this' holds the current audioElement.
162 // In this jQuery loop, variable 'this' holds the current audioElement. 160
163 161 var audioObject = audioEngineContext.newTrack(element);
164 var audioObject = audioEngineContext.newTrack(element); 162 if (element.type == 'outside-reference') {
165 if (element.type == 'outside-reference') 163 // Construct outside reference;
166 { 164 var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder"));
167 // Construct outside reference; 165 audioObject.bindInterface(orNode);
168 var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); 166 } else {
169 audioObject.bindInterface(orNode); 167 // Create a slider per track
170 } else { 168 switch (audioObject.specification.parent.label) {
171 // Create a slider per track
172 switch(audioObject.specification.parent.label) {
173 case "none": 169 case "none":
174 label = ""; 170 label = "";
175 break; 171 break;
176 case "letter": 172 case "letter":
177 label = String.fromCharCode(97 + index); 173 label = String.fromCharCode(97 + index);
178 break; 174 break;
179 case "capital": 175 case "capital":
180 label = String.fromCharCode(65 + index); 176 label = String.fromCharCode(65 + index);
181 break; 177 break;
182 default: 178 default:
183 label = ""+index; 179 label = "" + index;
184 break; 180 break;
185 } 181 }
186 var sliderObj = new sliderObject(audioObject,label); 182 var sliderObj = new sliderObject(audioObject, label);
187 183
188 if (typeof page.initialPosition === "number") 184 if (typeof page.initialPosition === "number") {
189 { 185 // Set the values
190 // Set the values 186 sliderObj.slider.value = page.initalPosition;
191 sliderObj.slider.value = page.initalPosition; 187 } else {
192 } else { 188 // Distribute it randomnly
193 // Distribute it randomnly 189 sliderObj.slider.value = Math.random();
194 sliderObj.slider.value = Math.random(); 190 }
195 } 191 sliderBox.appendChild(sliderObj.holder);
196 sliderBox.appendChild(sliderObj.holder); 192 audioObject.bindInterface(sliderObj);
197 audioObject.bindInterface(sliderObj);
198 interfaceContext.commentBoxes.createCommentBox(audioObject); 193 interfaceContext.commentBoxes.createCommentBox(audioObject);
199 index += 1; 194 index += 1;
200 } 195 }
201 196
202 }); 197 });
203 var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); 198 var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options);
204 for (var option of interfaceOptions) 199 for (var option of interfaceOptions) {
205 { 200 if (option.type == "show") {
206 if (option.type == "show") 201 switch (option.name) {
207 {
208 switch(option.name) {
209 case "playhead": 202 case "playhead":
210 var playbackHolder = document.getElementById('playback-holder'); 203 var playbackHolder = document.getElementById('playback-holder');
211 if (playbackHolder == null) 204 if (playbackHolder == null) {
212 {
213 playbackHolder = document.createElement('div'); 205 playbackHolder = document.createElement('div');
214 playbackHolder.style.width = "100%"; 206 playbackHolder.style.width = "100%";
215 playbackHolder.align = 'center'; 207 playbackHolder.align = 'center';
216 playbackHolder.appendChild(interfaceContext.playhead.object); 208 playbackHolder.appendChild(interfaceContext.playhead.object);
217 feedbackHolder.appendChild(playbackHolder); 209 feedbackHolder.appendChild(playbackHolder);
218 } 210 }
219 break; 211 break;
220 case "page-count": 212 case "page-count":
221 var pagecountHolder = document.getElementById('page-count'); 213 var pagecountHolder = document.getElementById('page-count');
222 if (pagecountHolder == null) 214 if (pagecountHolder == null) {
223 {
224 pagecountHolder = document.createElement('div'); 215 pagecountHolder = document.createElement('div');
225 pagecountHolder.id = 'page-count'; 216 pagecountHolder.id = 'page-count';
226 } 217 }
227 pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; 218 pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>';
228 var inject = document.getElementById('interface-buttons'); 219 var inject = document.getElementById('interface-buttons');
229 inject.appendChild(pagecountHolder); 220 inject.appendChild(pagecountHolder);
230 break; 221 break;
231 case "volume": 222 case "volume":
232 if (document.getElementById('master-volume-holder') == null) 223 if (document.getElementById('master-volume-holder') == null) {
233 {
234 feedbackHolder.appendChild(interfaceContext.volume.object); 224 feedbackHolder.appendChild(interfaceContext.volume.object);
235 } 225 }
236 break; 226 break;
237 case "comments": 227 case "comments":
238 interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); 228 interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true);
239 break; 229 break;
240 } 230 }
241 } 231 }
242 } 232 }
243 // Auto-align 233 // Auto-align
244 resizeWindow(null); 234 resizeWindow(null);
245 } 235 }
246 236
247 function sliderObject(audioObject,label) 237 function sliderObject(audioObject, label) {
248 { 238 // An example node, you can make this however you want for each audioElement.
249 // An example node, you can make this however you want for each audioElement. 239 // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following
250 // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following 240 // You attach them by calling audioObject.bindInterface( )
251 // You attach them by calling audioObject.bindInterface( ) 241 this.parent = audioObject;
252 this.parent = audioObject; 242
253 243 this.holder = document.createElement('div');
254 this.holder = document.createElement('div'); 244 this.title = document.createElement('div');
255 this.title = document.createElement('div'); 245 this.slider = document.createElement('input');
256 this.slider = document.createElement('input'); 246 this.play = document.createElement('button');
257 this.play = document.createElement('button'); 247
258 248 this.holder.className = 'track-slider';
259 this.holder.className = 'track-slider'; 249 this.holder.style.width = window.innerWidth - 200 + 'px';
260 this.holder.style.width = window.innerWidth-200 + 'px'; 250 this.holder.appendChild(this.title);
261 this.holder.appendChild(this.title); 251 this.holder.appendChild(this.slider);
262 this.holder.appendChild(this.slider); 252 this.holder.appendChild(this.play);
263 this.holder.appendChild(this.play); 253 this.holder.setAttribute('trackIndex', audioObject.id);
264 this.holder.setAttribute('trackIndex',audioObject.id); 254 this.title.textContent = label;
265 this.title.textContent = label; 255 this.title.className = 'track-slider-title';
266 this.title.className = 'track-slider-title'; 256
267 257 this.slider.type = "range";
268 this.slider.type = "range"; 258 this.slider.className = "track-slider-range track-slider-not-moved";
269 this.slider.className = "track-slider-range track-slider-not-moved"; 259 this.slider.min = "0";
270 this.slider.min = "0"; 260 this.slider.max = "1";
271 this.slider.max = "1"; 261 this.slider.step = "0.01";
272 this.slider.step = "0.01"; 262 this.slider.style.width = window.innerWidth - 420 + 'px';
273 this.slider.style.width = window.innerWidth-420 + 'px'; 263 this.slider.onchange = function () {
274 this.slider.onchange = function() 264 var time = audioEngineContext.timer.getTestTime();
275 { 265 var id = Number(this.parentNode.getAttribute('trackIndex'));
276 var time = audioEngineContext.timer.getTestTime(); 266 audioEngineContext.audioObjects[id].metric.moved(time, this.value);
277 var id = Number(this.parentNode.getAttribute('trackIndex')); 267 console.log('slider ' + id + ' moved to ' + this.value + ' (' + time + ')');
278 audioEngineContext.audioObjects[id].metric.moved(time,this.value); 268 $(this).removeClass('track-slider-not-moved');
279 console.log('slider '+id+' moved to '+this.value+' ('+time+')'); 269 };
280 $(this).removeClass('track-slider-not-moved'); 270
281 }; 271 this.play.className = 'track-slider-button';
282 272 this.play.textContent = "Loading...";
283 this.play.className = 'track-slider-button'; 273 this.play.value = audioObject.id;
284 this.play.textContent = "Loading..."; 274 this.play.disabled = true;
285 this.play.value = audioObject.id; 275 this.play.setAttribute("playstate", "ready");
286 this.play.disabled = true; 276 this.play.onclick = function (event) {
287 this.play.setAttribute("playstate","ready"); 277 var id = Number(event.currentTarget.value);
288 this.play.onclick = function(event) 278 //audioEngineContext.metric.sliderPlayed(id);
289 { 279 if (event.currentTarget.getAttribute("playstate") == "ready") {
290 var id = Number(event.currentTarget.value); 280 audioEngineContext.play(id);
291 //audioEngineContext.metric.sliderPlayed(id); 281 } else if (event.currentTarget.getAttribute("playstate") == "playing") {
292 if (event.currentTarget.getAttribute("playstate") == "ready") 282 audioEngineContext.stop();
293 {audioEngineContext.play(id);} 283 }
294 else if (event.currentTarget.getAttribute("playstate") == "playing") 284 };
295 {audioEngineContext.stop();} 285 this.resize = function (event) {
296 }; 286 this.holder.style.width = window.innerWidth - 200 + 'px';
297 this.resize = function(event) 287 this.slider.style.width = window.innerWidth - 420 + 'px';
298 { 288 };
299 this.holder.style.width = window.innerWidth-200 + 'px'; 289 this.enable = function () {
300 this.slider.style.width = window.innerWidth-420 + 'px'; 290 // This is used to tell the interface object that playback of this node is ready
301 }; 291 this.play.disabled = false;
302 this.enable = function() 292 this.play.textContent = "Play";
303 { 293 $(this.slider).removeClass('track-slider-disabled');
304 // This is used to tell the interface object that playback of this node is ready 294 };
305 this.play.disabled = false; 295 this.updateLoading = function (progress) {
306 this.play.textContent = "Play"; 296 // progress is a value from 0 to 100 indicating the current download state of media files
307 $(this.slider).removeClass('track-slider-disabled'); 297 };
308 }; 298 this.startPlayback = function () {
309 this.updateLoading = function(progress)
310 {
311 // progress is a value from 0 to 100 indicating the current download state of media files
312 };
313 this.startPlayback = function()
314 {
315 // Called when playback has begun 299 // Called when playback has begun
316 this.play.setAttribute("playstate","playing"); 300 this.play.setAttribute("playstate", "playing");
317 $(".track-slider").removeClass('track-slider-playing'); 301 $(".track-slider").removeClass('track-slider-playing');
318 $(this.holder).addClass('track-slider-playing'); 302 $(this.holder).addClass('track-slider-playing');
319 var outsideReference = document.getElementById('outside-reference'); 303 var outsideReference = document.getElementById('outside-reference');
320 if (outsideReference != null) { 304 if (outsideReference != null) {
321 $(outsideReference).removeClass('track-slider-playing'); 305 $(outsideReference).removeClass('track-slider-playing');
322 } 306 }
323 }; 307 };
324 this.stopPlayback = function() 308 this.stopPlayback = function () {
325 {
326 // Called when playback has stopped. This gets called even if playback never started! 309 // Called when playback has stopped. This gets called even if playback never started!
327 this.play.setAttribute("playstate","ready"); 310 this.play.setAttribute("playstate", "ready");
328 $(this.holder).removeClass('track-slider-playing'); 311 $(this.holder).removeClass('track-slider-playing');
329 }; 312 };
330 this.getValue = function() 313 this.getValue = function () {
331 { 314 // Return the current value of the object. If there is no value, return 0
332 // Return the current value of the object. If there is no value, return 0 315 return this.slider.value;
333 return this.slider.value; 316 };
334 }; 317 this.getPresentedId = function () {
335 this.getPresentedId = function() 318 // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale
336 { 319 return this.title.textContent;
337 // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale 320 };
338 return this.title.textContent; 321 this.canMove = function () {
339 }; 322 // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale.
340 this.canMove = function() 323 // These are checked primarily if the interface check option 'fragmentMoved' is enabled.
341 { 324 return true;
342 // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. 325 };
343 // These are checked primarily if the interface check option 'fragmentMoved' is enabled. 326 this.exportXMLDOM = function (audioObject) {
344 return true; 327 // Called by the audioObject holding this element to export the interface <value> node.
345 }; 328 // If there is no value node (such as outside reference), return null
346 this.exportXMLDOM = function(audioObject) { 329 // 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
347 // Called by the audioObject holding this element to export the interface <value> node. 330 // Use storage.document.createElement('value'); to generate the XML node.
348 // If there is no value node (such as outside reference), return null 331 var node = storage.document.createElement('value');
349 // 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
350 // Use storage.document.createElement('value'); to generate the XML node.
351 var node = storage.document.createElement('value');
352 node.textContent = this.slider.value; 332 node.textContent = this.slider.value;
353 return node; 333 return node;
354 }; 334 };
355 this.error = function() { 335 this.error = function () {
356 // audioObject has an error!! 336 // audioObject has an error!!
357 this.playback.textContent = "Error"; 337 this.playback.textContent = "Error";
358 $(this.playback).addClass("error-colour"); 338 $(this.playback).addClass("error-colour");
359 } 339 }
360 }; 340 };
361 341
362 function resizeWindow(event) 342 function resizeWindow(event) {
363 { 343 // Called on every window resize event, use this to scale your page properly
364 // Called on every window resize event, use this to scale your page properly 344
365 345 var numObj = document.getElementsByClassName('track-slider').length;
366 var numObj = document.getElementsByClassName('track-slider').length; 346 var totalHeight = (numObj * 125) - 25;
367 var totalHeight = (numObj * 125)-25; 347 document.getElementById('scale-holder').style.width = window.innerWidth - 220 + 'px';
368 document.getElementById('scale-holder').style.width = window.innerWidth-220 + 'px'; 348 // Cheers edge for making me delete a canvas every resize.
369 // Cheers edge for making me delete a canvas every resize. 349 var canvas = document.getElementById('scale-canvas');
370 var canvas = document.getElementById('scale-canvas');
371 var new_canvas = document.createElement("canvas"); 350 var new_canvas = document.createElement("canvas");
372 new_canvas.id = 'scale-canvas'; 351 new_canvas.id = 'scale-canvas';
373 new_canvas.style.marginLeft = "100px"; 352 new_canvas.style.marginLeft = "100px";
374 canvas.parentElement.appendChild(new_canvas); 353 canvas.parentElement.appendChild(new_canvas);
375 canvas.parentElement.removeChild(canvas); 354 canvas.parentElement.removeChild(canvas);
376 new_canvas.width = window.innerWidth-420; 355 new_canvas.width = window.innerWidth - 420;
377 new_canvas.height = totalHeight; 356 new_canvas.height = totalHeight;
378 for (var i in audioEngineContext.audioObjects) 357 for (var i in audioEngineContext.audioObjects) {
379 { 358 if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference') {
380 if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference'){ 359 audioEngineContext.audioObjects[i].interfaceDOM.resize(event);
381 audioEngineContext.audioObjects[i].interfaceDOM.resize(event); 360 }
382 } 361 }
383 } 362 document.getElementById("slider").style.height = totalHeight + 50 + 'px';
384 document.getElementById("slider").style.height = totalHeight+50+'px'; 363 drawScale();
385 drawScale();
386 } 364 }
387 365
388 function drawScale() 366 function drawScale() {
389 { 367 var interfaceObj = testState.currentStateMap.interfaces[0];
390 var interfaceObj = testState.currentStateMap.interfaces[0]; 368 var scales = testState.currentStateMap.interfaces[0].scales;
391 var scales = testState.currentStateMap.interfaces[0].scales; 369 scales = scales.sort(function (a, b) {
392 scales = scales.sort(function(a,b) { 370 return a.position - b.position;
393 return a.position - b.position; 371 });
394 }); 372 var canvas = document.getElementById('scale-canvas');
395 var canvas = document.getElementById('scale-canvas'); 373 var ctx = canvas.getContext("2d");
396 var ctx = canvas.getContext("2d"); 374 var height = canvas.height;
397 var height = canvas.height; 375 var width = canvas.width;
398 var width = canvas.width; 376 var textHolder = document.getElementById('scale-text-holder');
399 var textHolder = document.getElementById('scale-text-holder'); 377 textHolder.innerHTML = "";
400 textHolder.innerHTML = ""; 378 ctx.fillStyle = "#000000";
401 ctx.fillStyle = "#000000"; 379 ctx.setLineDash([1, 4]);
402 ctx.setLineDash([1,4]); 380 for (var scale of scales) {
403 for (var scale of scales) 381 var posPercent = scale.position / 100.0;
404 { 382 var posPix = Math.round(width * posPercent);
405 var posPercent = scale.position / 100.0; 383 if (posPix <= 0) {
406 var posPix = Math.round(width * posPercent); 384 posPix = 1;
407 if(posPix<=0){posPix=1;} 385 }
408 if(posPix>=width){posPix=width-1;} 386 if (posPix >= width) {
409 ctx.moveTo(posPix,0); 387 posPix = width - 1;
410 ctx.lineTo(posPix,height); 388 }
411 ctx.stroke(); 389 ctx.moveTo(posPix, 0);
412 390 ctx.lineTo(posPix, height);
413 var text = document.createElement('div'); 391 ctx.stroke();
414 text.align = "center"; 392
415 var textC = document.createElement('span'); 393 var text = document.createElement('div');
416 textC.textContent = scale.text; 394 text.align = "center";
417 text.appendChild(textC); 395 var textC = document.createElement('span');
418 text.className = "scale-text"; 396 textC.textContent = scale.text;
419 textHolder.appendChild(text); 397 text.appendChild(textC);
420 text.style.width = Math.ceil($(text).width())+'px'; 398 text.className = "scale-text";
421 text.style.left = (posPix+100-($(text).width()/2)) +'px'; 399 textHolder.appendChild(text);
422 } 400 text.style.width = Math.ceil($(text).width()) + 'px';
401 text.style.left = (posPix + 100 - ($(text).width() / 2)) + 'px';
402 }
423 } 403 }
424 404
425 function buttonSubmitClick() // TODO: Only when all songs have been played! 405 function buttonSubmitClick() // TODO: Only when all songs have been played!
426 { 406 {
427 var checks = []; 407 var checks = [];
428 checks = checks.concat(testState.currentStateMap.interfaces[0].options); 408 checks = checks.concat(testState.currentStateMap.interfaces[0].options);
429 checks = checks.concat(specification.interfaces.options); 409 checks = checks.concat(specification.interfaces.options);
430 var canContinue = true; 410 var canContinue = true;
431 411
432 // Check that the anchor and reference objects are correctly placed 412 // Check that the anchor and reference objects are correctly placed
433 if (interfaceContext.checkHiddenAnchor() == false) {return;} 413 if (interfaceContext.checkHiddenAnchor() == false) {
434 if (interfaceContext.checkHiddenReference() == false) {return;} 414 return;
435 415 }
436 for (var i=0; i<checks.length; i++) { 416 if (interfaceContext.checkHiddenReference() == false) {
437 if (checks[i].type == 'check') 417 return;
438 { 418 }
439 switch(checks[i].name) { 419
440 case 'fragmentPlayed': 420 for (var i = 0; i < checks.length; i++) {
441 // Check if all fragments have been played 421 if (checks[i].type == 'check') {
442 var checkState = interfaceContext.checkAllPlayed(); 422 switch (checks[i].name) {
443 if (checkState == false) {canContinue = false;} 423 case 'fragmentPlayed':
444 break; 424 // Check if all fragments have been played
445 case 'fragmentFullPlayback': 425 var checkState = interfaceContext.checkAllPlayed();
446 // Check all fragments have been played to their full length 426 if (checkState == false) {
447 var checkState = interfaceContext.checkAllPlayed(); 427 canContinue = false;
448 if (checkState == false) {canContinue = false;} 428 }
449 console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); 429 break;
450 break; 430 case 'fragmentFullPlayback':
451 case 'fragmentMoved': 431 // Check all fragments have been played to their full length
452 // Check all fragment sliders have been moved. 432 var checkState = interfaceContext.checkAllPlayed();
453 var checkState = interfaceContext.checkAllMoved(); 433 if (checkState == false) {
454 if (checkState == false) {canContinue = false;} 434 canContinue = false;
455 break; 435 }
456 case 'fragmentComments': 436 console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead');
457 // Check all fragment sliders have been moved. 437 break;
458 var checkState = interfaceContext.checkAllCommented(); 438 case 'fragmentMoved':
459 if (checkState == false) {canContinue = false;} 439 // Check all fragment sliders have been moved.
460 break; 440 var checkState = interfaceContext.checkAllMoved();
461 case 'scalerange': 441 if (checkState == false) {
462 // Check the scale has been used effectively 442 canContinue = false;
463 var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); 443 }
464 if (checkState == false) {canContinue = false;} 444 break;
465 break; 445 case 'fragmentComments':
466 default: 446 // Check all fragment sliders have been moved.
467 console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); 447 var checkState = interfaceContext.checkAllCommented();
468 break; 448 if (checkState == false) {
469 } 449 canContinue = false;
470 450 }
471 } 451 break;
472 if (!canContinue) {break;} 452 case 'scalerange':
473 } 453 // Check the scale has been used effectively
474 454 var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max);
455 if (checkState == false) {
456 canContinue = false;
457 }
458 break;
459 default:
460 console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface");
461 break;
462 }
463
464 }
465 if (!canContinue) {
466 break;
467 }
468 }
469
475 if (canContinue) { 470 if (canContinue) {
476 if (audioEngineContext.status == 1) { 471 if (audioEngineContext.status == 1) {
477 var playback = document.getElementById('playback-button'); 472 var playback = document.getElementById('playback-button');
478 playback.click(); 473 playback.click();
479 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options 474 // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options
480 } else 475 } else {
481 { 476 if (audioEngineContext.timer.testStarted == false) {
482 if (audioEngineContext.timer.testStarted == false) 477 interfaceContext.lightbox.post("Warning", 'You have not started the test! Please press start to begin the test!');
483 { 478 return;
484 interfaceContext.lightbox.post("Warning",'You have not started the test! Please press start to begin the test!'); 479 }
485 return; 480 }
486 } 481 testState.advanceState();
487 } 482 }
488 testState.advanceState();
489 }
490 } 483 }
491 484
492 function pageXMLSave(store, pageSpecification) 485 function pageXMLSave(store, pageSpecification) {
493 { 486 // MANDATORY
494 // MANDATORY 487 // Saves a specific test page
495 // Saves a specific test page 488 // You can use this space to add any extra nodes to your XML <audioHolder> saves
496 // You can use this space to add any extra nodes to your XML <audioHolder> saves 489 // Get the current <page> information in store (remember to appendChild your data to it)
497 // Get the current <page> information in store (remember to appendChild your data to it) 490 // pageSpecification is the current page node configuration
498 // pageSpecification is the current page node configuration 491 // To create new XML nodes, use storage.document.createElement();
499 // To create new XML nodes, use storage.document.createElement();
500 } 492 }