Mercurial > hg > webaudioevaluationtool
comparison interfaces/ape.js @ 3009:1ced6e0cb9ac
Refactorised ape.js. Now uses modular system to manage interface (WIP)
author | Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk> |
---|---|
date | Fri, 04 Aug 2017 10:03:56 +0200 |
parents | 64a5603831e2 |
children | 7bbf1b1bfd95 |
comparison
equal
deleted
inserted
replaced
3008:166c5aef020c | 3009:1ced6e0cb9ac |
---|---|
5 | 5 |
6 /*globals window,interfaceContext, document, audioEngineContext, console, $, Interface, testState, storage, specification */ | 6 /*globals window,interfaceContext, document, audioEngineContext, console, $, Interface, testState, storage, specification */ |
7 /*globals metricTracker */ | 7 /*globals metricTracker */ |
8 // Once this is loaded and parsed, begin execution | 8 // Once this is loaded and parsed, begin execution |
9 loadInterface(); | 9 loadInterface(); |
10 window.APE = undefined; | |
10 | 11 |
11 function loadInterface() { | 12 function loadInterface() { |
12 | 13 |
13 // Get the dimensions of the screen available to the page | 14 // Get the dimensions of the screen available to the page |
14 var width = window.innerWidth; | 15 var width = window.innerWidth; |
122 console.log(str); | 123 console.log(str); |
123 } | 124 } |
124 return state; | 125 return state; |
125 }; | 126 }; |
126 | 127 |
127 Interface.prototype.objectSelected = null; | |
128 Interface.prototype.objectMoved = false; | |
129 Interface.prototype.selectObject = function (object) { | |
130 if (this.objectSelected === null) { | |
131 this.objectSelected = object; | |
132 this.objectMoved = false; | |
133 } | |
134 }; | |
135 Interface.prototype.moveObject = function () { | |
136 if (this.objectMoved === false) { | |
137 this.objectMoved = true; | |
138 } | |
139 }; | |
140 Interface.prototype.releaseObject = function () { | |
141 this.objectSelected = null; | |
142 this.objectMoved = false; | |
143 }; | |
144 Interface.prototype.getSelectedObject = function () { | |
145 return this.objectSelected; | |
146 }; | |
147 Interface.prototype.hasSelectedObjectMoved = function () { | |
148 return this.objectMoved; | |
149 }; | |
150 | |
151 // Bindings for slider interfaces | |
152 Interface.prototype.interfaceSliders = []; | |
153 | |
154 // Bindings for audioObjects | 128 // Bindings for audioObjects |
155 | 129 |
156 // Create the top div for the Title element | 130 // Create the top div for the Title element |
157 var titleAttr = specification.title; | 131 var titleAttr = specification.title; |
158 var title = document.createElement('div'); | 132 var title = document.createElement('div'); |
218 testContent.appendChild(sliderHolder); | 192 testContent.appendChild(sliderHolder); |
219 testContent.appendChild(feedbackHolder); | 193 testContent.appendChild(feedbackHolder); |
220 interfaceContext.insertPoint.appendChild(testContent); | 194 interfaceContext.insertPoint.appendChild(testContent); |
221 | 195 |
222 // Load the full interface | 196 // Load the full interface |
197 window.APE = new ape(); | |
223 testState.initialise(); | 198 testState.initialise(); |
224 testState.advanceState(); | 199 testState.advanceState(); |
225 | |
226 } | 200 } |
227 | 201 |
228 function loadTest(audioHolderObject) { | 202 function loadTest(audioHolderObject) { |
203 APE.clear(); | |
229 var width = window.innerWidth; | 204 var width = window.innerWidth; |
230 var height = window.innerHeight; | 205 var height = window.innerHeight; |
231 var id = audioHolderObject.id; | 206 var id = audioHolderObject.id; |
232 | 207 |
233 interfaceContext.interfaceSliders = []; | 208 interfaceContext.interfaceSliders = []; |
244 // Set the page title | 219 // Set the page title |
245 if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { | 220 if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { |
246 document.getElementById("test-title").textContent = audioHolderObject.title; | 221 document.getElementById("test-title").textContent = audioHolderObject.title; |
247 } | 222 } |
248 | 223 |
249 | |
250 // Delete outside reference | 224 // Delete outside reference |
251 document.getElementById("outside-reference-holder").innerHTML = ""; | 225 document.getElementById("outside-reference-holder").innerHTML = ""; |
252 | 226 |
253 var interfaceObj = interfaceContext.getCombinedInterfaces(audioHolderObject); | 227 var interfaceObj = interfaceContext.getCombinedInterfaces(audioHolderObject); |
254 interfaceObj.forEach(function (interfaceObjectInstance) { | |
255 // Create the div box to center align | |
256 interfaceContext.interfaceSliders.push(new interfaceSliderHolder(interfaceObjectInstance, audioHolderObject)); | |
257 }); | |
258 interfaceObj.forEach(function (interface) { | 228 interfaceObj.forEach(function (interface) { |
259 interface.options.forEach(function (option) { | 229 interface.options.forEach(function (option) { |
260 if (option.type == "show") { | 230 if (option.type == "show") { |
261 switch (option.name) { | 231 switch (option.name) { |
262 case "playhead": | 232 case "playhead": |
296 | 266 |
297 var commentShow = audioHolderObject.elementComments; | 267 var commentShow = audioHolderObject.elementComments; |
298 | 268 |
299 var loopPlayback = audioHolderObject.loop; | 269 var loopPlayback = audioHolderObject.loop; |
300 | 270 |
301 var currentTestHolder = document.createElement('audioHolder'); | 271 APE.initialisePage(audioHolderObject); |
302 currentTestHolder.id = audioHolderObject.id; | |
303 currentTestHolder.repeatCount = audioHolderObject.repeatCount; | |
304 | |
305 // Find all the audioElements from the audioHolder | |
306 $(audioHolderObject.audioElements).each(function (index, element) { | |
307 // Find URL of track | |
308 // In this jQuery loop, variable 'this' holds the current audioElement. | |
309 var audioObject = audioEngineContext.newTrack(element); | |
310 // Check if an outside reference | |
311 if (element.type == 'outside-reference') { | |
312 // Construct outside reference; | |
313 var orNode = new outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); | |
314 audioObject.bindInterface(orNode); | |
315 } else { | |
316 // Create a slider per track | |
317 var sliderNode = new sliderObject(audioObject, interfaceObj, index); | |
318 audioObject.bindInterface(sliderNode); | |
319 interfaceContext.commentBoxes.createCommentBox(audioObject); | |
320 } | |
321 }); | |
322 | |
323 // Initialse the interfaceSlider object metrics | |
324 | |
325 $('.track-slider').mousedown(function (event) { | |
326 interfaceContext.selectObject($(this)[0]); | |
327 }); | |
328 $('.track-slider').on('touchstart', null, function (event) { | |
329 interfaceContext.selectObject($(this)[0]); | |
330 }); | |
331 | |
332 $('.track-slider').mousemove(function (event) { | |
333 event.preventDefault(); | |
334 }); | |
335 | |
336 $('.slider').mousemove(function (event) { | |
337 event.preventDefault(); | |
338 var obj = interfaceContext.getSelectedObject(); | |
339 if (obj === null) { | |
340 return; | |
341 } | |
342 var move = event.clientX - 6; | |
343 var w = $(event.currentTarget).width(); | |
344 move = Math.max(50, move); | |
345 move = Math.min(w + 50, move); | |
346 $(obj).css("left", move + "px"); | |
347 interfaceContext.moveObject(); | |
348 }); | |
349 | |
350 $('.slider').on('touchmove', null, function (event) { | |
351 event.preventDefault(); | |
352 var obj = interfaceContext.getSelectedObject(); | |
353 if (obj === null) { | |
354 return; | |
355 } | |
356 var move = event.originalEvent.targetTouches[0].clientX - 6; | |
357 var w = $(event.currentTarget).width(); | |
358 move = Math.max(50, move); | |
359 move = Math.min(w + 50, move); | |
360 $(obj).css("left", move + "px"); | |
361 interfaceContext.moveObject(); | |
362 }); | |
363 | |
364 $(document).mouseup(function (event) { | |
365 event.preventDefault(); | |
366 var obj = interfaceContext.getSelectedObject(); | |
367 if (obj === null) { | |
368 return; | |
369 } | |
370 var interfaceID = obj.parentElement.getAttribute("interfaceid"); | |
371 var trackID = obj.getAttribute("trackindex"); | |
372 var id; | |
373 if (interfaceContext.hasSelectedObjectMoved() === true) { | |
374 var l = $(obj).css("left"); | |
375 id = obj.getAttribute('trackIndex'); | |
376 var time = audioEngineContext.timer.getTestTime(); | |
377 var rate = convSliderPosToRate(obj); | |
378 audioEngineContext.audioObjects[id].metric.moved(time, rate); | |
379 interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time, rate); | |
380 console.log("slider " + id + " moved to " + rate + ' (' + time + ')'); | |
381 obj.setAttribute("slider-value", convSliderPosToRate(obj)); | |
382 } else { | |
383 id = Number(obj.attributes.trackIndex.value); | |
384 //audioEngineContext.metric.sliderPlayed(id); | |
385 audioEngineContext.play(id); | |
386 } | |
387 interfaceContext.releaseObject(); | |
388 }); | |
389 | |
390 $('.slider').on('touchend', null, function (event) { | |
391 var obj = interfaceContext.getSelectedObject(); | |
392 if (obj === null) { | |
393 return; | |
394 } | |
395 var interfaceID = obj.parentElement.getAttribute("interfaceid"); | |
396 var trackID = obj.getAttribute("trackindex"); | |
397 if (interfaceContext.hasSelectedObjectMoved() === true) { | |
398 var l = $(obj).css("left"); | |
399 var id = obj.getAttribute('trackIndex'); | |
400 var time = audioEngineContext.timer.getTestTime(); | |
401 var rate = convSliderPosToRate(obj); | |
402 audioEngineContext.audioObjects[id].metric.moved(time, rate); | |
403 interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time, rate); | |
404 console.log("slider " + id + " moved to " + rate + ' (' + time + ')'); | |
405 } | |
406 interfaceContext.releaseObject(); | |
407 }); | |
408 | 272 |
409 var interfaceList = audioHolderObject.interfaces.concat(specification.interfaces); | 273 var interfaceList = audioHolderObject.interfaces.concat(specification.interfaces); |
410 for (var k = 0; k < interfaceList.length; k++) { | 274 for (var k = 0; k < interfaceList.length; k++) { |
411 for (var i = 0; i < interfaceList[k].options.length; i++) { | 275 for (var i = 0; i < interfaceList[k].options.length; i++) { |
412 if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') { | 276 if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') { |
445 }); | 309 }); |
446 | 310 |
447 //testWaitIndicator(); | 311 //testWaitIndicator(); |
448 } | 312 } |
449 | 313 |
450 function interfaceSliderHolder(interfaceObject, page) { | 314 function ape() { |
451 this.sliders = []; | 315 var axis = [] |
452 this.metrics = []; | 316 var DOMRoot = document.getElementById("slider-holder"); |
453 this.id = document.getElementsByClassName("sliderCanvasDiv").length; | 317 var AOIs = []; |
454 this.name = interfaceObject.name; | 318 var page = undefined; |
455 this.interfaceObject = interfaceObject; | 319 |
456 this.sliderDOM = document.createElement('div'); | 320 function audioObjectInterface(audioObject, parent) { |
457 this.sliderDOM.className = 'sliderCanvasDiv'; | 321 // The audioObject communicates with this object |
458 this.sliderDOM.id = 'sliderCanvasHolder-' + this.id; | 322 var playing = false; |
459 this.imageHolder = (function () { | 323 var sliders = []; |
460 var imageController = {}; | 324 this.enable = function () { |
461 imageController.root = document.createElement("div"); | 325 sliders.forEach(function (s) { |
462 imageController.root.className = "imageController"; | 326 s.enable(); |
463 imageController.img = document.createElement("img"); | 327 }) |
464 imageController.root.appendChild(imageController.img); | 328 } |
465 imageController.setImage = function (src) { | 329 |
466 imageController.img.src = ""; | 330 this.updateLoading = function (p) { |
467 if (typeof src !== "string" || src.length === undefined) { | 331 sliders.forEach(function (s) { |
332 s.updateLoading(p); | |
333 }) | |
334 } | |
335 | |
336 this.startPlayback = function () { | |
337 playing = true; | |
338 sliders.forEach(function (s) { | |
339 s.playing(); | |
340 }); | |
341 } | |
342 | |
343 this.stopPlayback = function () { | |
344 playing = false; | |
345 sliders.forEach(function (s) { | |
346 s.stopped(); | |
347 }); | |
348 } | |
349 | |
350 this.getValue = function () { | |
351 return sliders[0].value(); | |
352 } | |
353 | |
354 this.getPresentedId = function () { | |
355 return sliders[0].label; | |
356 } | |
357 | |
358 this.canMove = function () { | |
359 return true; | |
360 } | |
361 | |
362 this.exportXMLDOM = function (audioObject) { | |
363 var elements = []; | |
364 sliders.forEach(function (s) { | |
365 elements.push(s.exportXMLDOM()); | |
366 }); | |
367 return elements; | |
368 } | |
369 | |
370 this.error = function () { | |
371 sliders.forEach(function (s) { | |
372 s.error(); | |
373 }); | |
374 } | |
375 | |
376 this.addSlider = function (s) { | |
377 sliders.push(s); | |
378 } | |
379 | |
380 this.clicked = function (event) { | |
381 if (!playing) { | |
382 audioEngineContext.play(audioObject.id); | |
383 } else { | |
384 audioEngineContext.stop(); | |
385 } | |
386 playing = !playing; | |
387 } | |
388 | |
389 this.pageXMLSave = function (store) { | |
390 var inject = audioObject.storeDOM.getElementsByTagName("metric")[0]; | |
391 sliders.forEach(function (s) { | |
392 s.pageXMLSave(inject); | |
393 }); | |
394 } | |
395 | |
396 } | |
397 | |
398 function axisObject(interfaceObject, parent) { | |
399 | |
400 function sliderInterface(AOI, axisInterface) { | |
401 var trackObj = document.createElement('div'); | |
402 var labelHolder = document.createElement("span"); | |
403 var label = ""; | |
404 var metric = new metricTracker(this); | |
405 trackObj.align = "center"; | |
406 trackObj.className = 'track-slider track-slider-disabled'; | |
407 trackObj.appendChild(labelHolder); | |
408 trackObj.style.left = (Math.random() * $(sliderRail).width()) - 50 + "px"; | |
409 axisInterface.sliderRail.appendChild(trackObj); | |
410 metric.initialise(this.value); | |
411 this.setLabel = function (s) { | |
412 label = s; | |
413 } | |
414 this.resize = function (event) { | |
415 var width = $(axisInterface.sliderRail).width(); | |
416 var w = Number(value * width + 50); | |
417 trackObj.style.left = String(w) + "px"; | |
418 } | |
419 this.playing = function () { | |
420 trackObj.classList.add("track-slider-playing"); | |
421 } | |
422 this.stopped = function () { | |
423 trackObj.classList.remove("track-slider-playing"); | |
424 } | |
425 this.enable = function () { | |
426 trackObj.addEventListener("mousedown", this); | |
427 trackObj.addEventListener("mouseup", this); | |
428 trackObj.addEventListener("touchstart", this); | |
429 trackObj.classList.remove("track-slider-disabled"); | |
430 labelHolder.textContent = label; | |
431 } | |
432 this.updateLoading = function (progress) { | |
433 labelHolder.textContent = progress + "%"; | |
434 } | |
435 this.exportXMLDOM = function () { | |
436 var node = storage.document.createElement('value'); | |
437 node.setAttribute("interface-name", axisInterface.name) | |
438 node.textContent = this.value(); | |
439 return node; | |
440 } | |
441 this.error = function () { | |
442 trackObj.classList.add("error-colour"); | |
443 trackObj.removeEventListener("mousedown"); | |
444 trackObj.removeEventListener("mouseup"); | |
445 trackObj.removeEventListener("touchstart"); | |
446 } | |
447 var timing = undefined; | |
448 this.handleEvent = function (e) { | |
449 // This is only for the mousedown / touchdown | |
450 if (e.preventDefault) { | |
451 e.preventDefault(); | |
452 } | |
453 if (e.type == "mousedown" || e.type == "touchstart") { | |
454 axisInterface.mousedown(this); | |
455 } else if (e.type == "mouseup") { | |
456 axisInterface.mouseup(this); | |
457 } | |
458 } | |
459 this.clicked = function (e) { | |
460 AOI.clicked(); | |
461 } | |
462 this.pageXMLSave = function (inject) { | |
463 var nodes = metric.exportXMLDOM(inject); | |
464 nodes.forEach(function (elem) { | |
465 var name = elem.getAttribute("name"); | |
466 if (name == "elementTracker" || name == "elementTrackerFull" || name == "elementInitialPosition" || name == "elementFlagMoved") { | |
467 mrnodes[j].setAttribute("interface-name", axisInterface.name); | |
468 } | |
469 }); | |
470 } | |
471 Object.defineProperties(this, { | |
472 "DOM": { | |
473 "value": trackObj | |
474 }, | |
475 "value": { | |
476 "value": function () { | |
477 var maxPix = $(axisInterface.sliderRail).width(); | |
478 var pix = trackObj.style.left.substr(0, trackObj.style.left.length - 2); | |
479 return (pix - 50) / maxPix; | |
480 } | |
481 }, | |
482 "moveToPixel": { | |
483 "value": function (pix) { | |
484 var t = audioEngineContext.timer.getTestTime(); | |
485 trackObj.style.left = String(pix) + "px"; | |
486 metric.moved(t, this.value); | |
487 } | |
488 }, | |
489 "label": { | |
490 "get": function () { | |
491 return label; | |
492 }, | |
493 "set": function () {} | |
494 } | |
495 }); | |
496 } | |
497 | |
498 function createScaleMarkers(interfaceObject, root, w) { | |
499 interfaceObject.scales.forEach(function (scaleObj) { | |
500 var position = Number(scaleObj.position) * 0.01; | |
501 var pixelPosition = (position * w) + 50; | |
502 var scaleDOM = document.createElement('span'); | |
503 scaleDOM.className = "ape-marker-text"; | |
504 scaleDOM.textContent = scaleObj.text; | |
505 scaleDOM.setAttribute('value', position); | |
506 root.appendChild(scaleDOM); | |
507 scaleDOM.style.left = Math.floor((pixelPosition - ($(scaleDOM).width() / 2))) + 'px'; | |
508 }, this); | |
509 } | |
510 var sliders = []; | |
511 var UI = { | |
512 selected: undefined, | |
513 startTime: undefined | |
514 } | |
515 this.name = interfaceObject.name; | |
516 var DOMRoot = document.createElement("div"); | |
517 DOMRoot.className = "sliderCanvasDiv"; | |
518 DOMRoot.id = "sliderCanvasHolder-" + this.name; | |
519 var sliders = []; | |
520 | |
521 var axisTitle = document.createElement("div"); | |
522 axisTitle.className = "pageTitle"; | |
523 axisTitle.align = "center"; | |
524 var titleSpan = document.createElement('span'); | |
525 titleSpan.id = "pageTitle-" + this.name; | |
526 if (interfaceObject.title !== undefined && typeof interfaceObject.title == "string") { | |
527 titleSpan.textContent = interfaceObject.title; | |
528 } else { | |
529 titleSpan.textContent = "Axis " + String(this.id + 1); | |
530 } | |
531 axisTitle.appendChild(titleSpan); | |
532 DOMRoot.appendChild(axisTitle); | |
533 | |
534 var imageHolder = (function () { | |
535 var imageController = {}; | |
536 imageController.root = document.createElement("div"); | |
537 imageController.root.className = "imageController"; | |
538 imageController.img = document.createElement("img"); | |
539 imageController.root.appendChild(imageController.img); | |
540 imageController.setImage = function (src) { | |
541 imageController.img.src = ""; | |
542 if (typeof src !== "string" || src.length === undefined) { | |
543 return; | |
544 } | |
545 imageController.img.src = src; | |
546 }; | |
547 return imageController; | |
548 })(); | |
549 if (interfaceObject.image !== undefined || page.audioElements.some(function (a) { | |
550 return a.image !== undefined; | |
551 })) { | |
552 DOMRoot.appendChild(imageHolder.root); | |
553 imageHolder.setImage(interfaceObject.image); | |
554 } | |
555 | |
556 // Now create the slider box to hold the fragment sliders | |
557 var sliderRail = document.createElement("div"); | |
558 sliderRail.id = "sliderrail-" + this.name; | |
559 sliderRail.className = "slider"; | |
560 sliderRail.align = "left"; | |
561 DOMRoot.appendChild(sliderRail); | |
562 | |
563 // Create the div to hold any scale objects | |
564 var scale = document.createElement("div"); | |
565 scale.className = "sliderScale"; | |
566 scale.id = "slider-scale-holder-" + this.name; | |
567 scale.slign = "left"; | |
568 DOMRoot.appendChild(scale); | |
569 createScaleMarkers(interfaceObject, scale, $(sliderRail).width()); | |
570 | |
571 parent.getDOMRoot().appendChild(DOMRoot); | |
572 | |
573 this.resize = function (event) { | |
574 var w = $(sliderRail).width(); | |
575 var marginsize = 50; | |
576 sliders.forEach(function (s) { | |
577 s.resize(); | |
578 }); | |
579 scale.innerHTML = ""; | |
580 createScaleMarkers(interfaceObject, scale, $(sliderRail).width()); | |
581 } | |
582 this.playing = function (id) { | |
583 var node = audioEngineContext.audioObjects.find(function (a) { | |
584 return a.id == id; | |
585 }); | |
586 if (node === undefined) { | |
587 this.imageHolder.setImage(interfaceObject.image || ""); | |
468 return; | 588 return; |
469 } | 589 } |
470 imageController.img.src = src; | 590 var imgurl = node.specification.image || interfaceObject.image || ""; |
471 }; | 591 this.imageHolder.setImage(imgurl); |
472 return imageController; | 592 } |
473 })(); | 593 this.stopped = function () { |
474 | 594 var imgurl = interfaceObject.image || ""; |
475 var pagetitle = document.createElement('div'); | 595 this.imageHolder.setImage(imgurl); |
476 pagetitle.className = "pageTitle"; | 596 } |
477 pagetitle.align = "center"; | 597 this.addSlider = function (aoi) { |
478 var titleSpan = document.createElement('span'); | 598 var node = new sliderInterface(aoi, this); |
479 titleSpan.id = "pageTitle-" + this.id; | 599 sliders.push(node); |
480 if (interfaceObject.title !== undefined && typeof interfaceObject.title == "string") { | 600 return node; |
481 titleSpan.textContent = interfaceObject.title; | 601 } |
482 } else { | 602 this.mousedown = function (sliderUI) { |
483 titleSpan.textContent = "Axis " + String(this.id + 1); | 603 UI.selected = sliderUI; |
484 } | 604 UI.startTime = new Date(); |
485 pagetitle.appendChild(titleSpan); | 605 } |
486 this.sliderDOM.appendChild(pagetitle); | 606 this.mouseup = function (sliderUI) { |
487 | 607 var delta = new Date() - UI.startTime; |
488 if (interfaceObject.image !== undefined || page.audioElements.some(function (a) { | 608 if (delta < 200) { |
489 return a.image !== undefined; | 609 UI.selected.clicked(); |
490 })) { | 610 } |
491 this.sliderDOM.appendChild(this.imageHolder.root); | 611 UI.selected = undefined; |
492 this.imageHolder.setImage(interfaceObject.image); | 612 UI.startTime = undefined; |
493 } | 613 } |
494 // Create the slider box to hold the slider elements | 614 this.handleEvent = function (event) { |
495 this.canvas = document.createElement('div'); | 615 if (event.preventDefault) { |
496 if (this.name !== undefined) | 616 event.preventDefault(); |
497 this.canvas.id = 'slider-' + this.name; | 617 } |
498 else | 618 if (UI.selected === undefined) { |
499 this.canvas.id = 'slider-' + this.id; | 619 return; |
500 this.canvas.setAttribute("interfaceid", this.id); | 620 } |
501 this.canvas.className = 'slider'; | 621 if (event.type == "mousemove") { |
502 this.canvas.align = "left"; | 622 var move = event.clientX - 6; |
503 this.canvas.addEventListener('dragover', function (event) { | 623 var w = $(sliderRail).width(); |
504 event.preventDefault(); | 624 move = Math.max(50, move); |
505 event.dataTransfer.effectAllowed = 'none'; | 625 move = Math.min(w + 50, move); |
506 event.dataTransfer.dropEffect = 'copy'; | 626 UI.selected.moveToPixel(move); |
507 return false; | 627 } else if (event.type == "touchmove") { |
508 }, false); | 628 var move = event.originalEvent.targetTouches[0].clientX - 6; |
509 this.sliderDOM.appendChild(this.canvas); | 629 var w = $(event.currentTarget).width(); |
510 | 630 move = Math.max(50, move); |
511 // Create the div to hold any scale objects | 631 move = Math.min(w + 50, move); |
512 this.scale = document.createElement('div'); | 632 UI.selected.moveToPixel(move); |
513 this.scale.className = 'sliderScale'; | 633 } |
514 this.scale.id = 'sliderScaleHolder-' + this.id; | 634 } |
515 this.scale.align = 'left'; | 635 sliderRail.addEventListener("mousemove", this); |
516 this.sliderDOM.appendChild(this.scale); | 636 sliderRail.addEventListener("touchmove", this); |
517 var positionScale = this.canvas.style.width.substr(0, this.canvas.style.width.length - 2); | 637 Object.defineProperties(this, { |
518 var offset = 50; | 638 "sliderRail": { |
519 var dest = document.getElementById("slider-holder").appendChild(this.sliderDOM); | 639 "value": sliderRail |
520 interfaceObject.scales.forEach(function (scaleObj) { | 640 } |
521 var position = Number(scaleObj.position) * 0.01; | |
522 var pixelPosition = (position * $(this.canvas).width()) + offset; | |
523 var scaleDOM = document.createElement('span'); | |
524 scaleDOM.className = "ape-marker-text"; | |
525 scaleDOM.textContent = scaleObj.text; | |
526 scaleDOM.setAttribute('value', position); | |
527 this.scale.appendChild(scaleDOM); | |
528 scaleDOM.style.left = Math.floor((pixelPosition - ($(scaleDOM).width() / 2))) + 'px'; | |
529 }, this); | |
530 | |
531 this.createSliderObject = function (audioObject, label) { | |
532 var trackObj = document.createElement('div'); | |
533 trackObj.align = "center"; | |
534 trackObj.className = 'track-slider track-slider-disabled track-slider-' + audioObject.id; | |
535 trackObj.id = 'track-slider-' + this.id + '-' + audioObject.id; | |
536 trackObj.setAttribute('trackIndex', audioObject.id); | |
537 if (this.name !== undefined) { | |
538 trackObj.setAttribute('interface-name', this.name); | |
539 } else { | |
540 trackObj.setAttribute('interface-name', this.id); | |
541 } | |
542 var offset = 50; | |
543 // Distribute it randomnly | |
544 var w = window.innerWidth - (offset + 8) * 2; | |
545 w = Math.random() * w; | |
546 w = Math.floor(w + (offset + 8)); | |
547 trackObj.style.left = w + 'px'; | |
548 this.canvas.appendChild(trackObj); | |
549 this.sliders.push(trackObj); | |
550 this.metrics.push(new metricTracker(this)); | |
551 var labelHolder = document.createElement("span"); | |
552 labelHolder.textContent = label; | |
553 trackObj.appendChild(labelHolder); | |
554 var rate = convSliderPosToRate(trackObj); | |
555 this.metrics[this.metrics.length - 1].initialise(rate); | |
556 trackObj.setAttribute("slider-value", rate); | |
557 return trackObj; | |
558 }; | |
559 | |
560 this.resize = function (event) { | |
561 var sliderDiv = this.canvas; | |
562 var sliderScaleDiv = this.scale; | |
563 var width = $(sliderDiv).width(); | |
564 var marginsize = 50; | |
565 // Move sliders into new position | |
566 this.sliders.forEach(function (slider, index) { | |
567 var pix = Number(slider.getAttribute("slider-value")) * width; | |
568 slider.style.left = (pix + marginsize) + 'px'; | |
569 }); | 641 }); |
570 | 642 } |
571 // Move scale labels | 643 this.getDOMRoot = function () { |
572 for (var index = 0; index < this.scale.children.length; index++) { | 644 return DOMRoot; |
573 var scaleObj = this.scale.children[index]; | 645 } |
574 var position = Number(scaleObj.attributes.value.value); | 646 this.getPage = function () { |
575 var pixelPosition = (position * width) + marginsize; | 647 return page; |
576 scaleObj.style.left = Math.floor((pixelPosition - ($(scaleObj).width() / 2))) + 'px'; | 648 } |
577 } | 649 this.clear = function () { |
578 }; | 650 page = undefined; |
579 | 651 axis = []; |
580 this.playing = function (id) { | 652 AOIs = []; |
581 var node = audioEngineContext.audioObjects.find(function (a) { | 653 DOMRoot.innerHTML = ""; |
582 return a.id == id; | 654 } |
655 this.initialisePage = function (page_init) { | |
656 this.clear(); | |
657 page = page_init; | |
658 var interfaceObj = interfaceContext.getCombinedInterfaces(page); | |
659 // Create each of the interface axis | |
660 interfaceObj.forEach(function (i) { | |
661 var node = new axisObject(i, this); | |
662 axis.push(node); | |
663 }, this); | |
664 | |
665 // Create the audioObject interface objects for each aO. | |
666 page.audioElements.forEach(function (element, index) { | |
667 var audioObject = audioEngineContext.newTrack(element); | |
668 if (element.type == 'outside-reference') { | |
669 // Construct outside reference; | |
670 var orNode = new outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); | |
671 audioObject.bindInterface(orNode); | |
672 } else { | |
673 var aoi = new audioObjectInterface(audioObject, this); | |
674 var label = interfaceContext.getLabel(page.label, index, page.labelStart); | |
675 axis.forEach(function (a) { | |
676 var node = a.addSlider(aoi); | |
677 node.setLabel(label); | |
678 aoi.addSlider(node); | |
679 audioObject.bindInterface(aoi); | |
680 }); | |
681 } | |
583 }); | 682 }); |
584 if (node === undefined) { | 683 } |
585 this.imageHolder.setImage(interfaceObject.image || ""); | 684 this.pageXMLSave = function (store, pageSpecification) { |
586 return; | 685 AOIs.forEach(function (ao) { |
587 } | 686 ao.pageXMLSave(store); |
588 var imgurl = node.specification.image || interfaceObject.image || ""; | |
589 this.imageHolder.setImage(imgurl); | |
590 } | |
591 } | |
592 | |
593 function sliderObject(audioObject, interfaceObjects, index) { | |
594 // Create a new slider object; | |
595 this.parent = audioObject; | |
596 this.trackSliderObjects = []; | |
597 this.label = interfaceContext.getLabel(audioObject.specification.parent.label, index, audioObject.specification.parent.labelStart); | |
598 this.playing = false; | |
599 for (var i = 0; i < interfaceContext.interfaceSliders.length; i++) { | |
600 var trackObj = interfaceContext.interfaceSliders[i].createSliderObject(audioObject, this.label); | |
601 this.trackSliderObjects.push(trackObj); | |
602 } | |
603 | |
604 // Onclick, switch playback to that track | |
605 | |
606 this.enable = function () { | |
607 if (this.parent.state == 1) { | |
608 $(this.trackSliderObjects).each(function (i, trackObj) { | |
609 $(trackObj).removeClass('track-slider-disabled'); | |
610 }); | |
611 } | |
612 }; | |
613 this.updateLoading = function (progress) { | |
614 if (progress != 100) { | |
615 progress = String(progress); | |
616 progress = progress.split('.')[0]; | |
617 this.trackSliderObjects[0].children[0].textContent = progress + '%'; | |
618 } else { | |
619 this.trackSliderObjects[0].children[0].textContent = this.label; | |
620 } | |
621 }; | |
622 this.startPlayback = function () { | |
623 $('.track-slider').removeClass('track-slider-playing'); | |
624 var name = ".track-slider-" + this.parent.id; | |
625 $(name).addClass('track-slider-playing'); | |
626 interfaceContext.commentBoxes.highlightById(audioObject.id); | |
627 $('.outside-reference').removeClass('track-slider-playing'); | |
628 this.playing = true; | |
629 | |
630 if (this.parent.specification.parent.playOne || specification.playOne) { | |
631 $('.track-slider').addClass('track-slider-disabled'); | |
632 $('.outside-reference').addClass('track-slider-disabled'); | |
633 } | |
634 interfaceContext.interfaceSliders.forEach(function (ts) { | |
635 ts.playing(this.parent.id); | |
636 }, this); | |
637 }; | |
638 this.stopPlayback = function () { | |
639 if (this.playing) { | |
640 this.playing = false; | |
641 var name = ".track-slider-" + this.parent.id; | |
642 $(name).removeClass('track-slider-playing'); | |
643 $('.track-slider').removeClass('track-slider-disabled'); | |
644 $('.outside-reference').removeClass('track-slider-disabled'); | |
645 var box = interfaceContext.commentBoxes.boxes.find(function (a) { | |
646 return a.id === audioObject.id; | |
647 }); | |
648 if (box) { | |
649 box.highlight(false); | |
650 } | |
651 } | |
652 }; | |
653 this.exportXMLDOM = function (audioObject) { | |
654 // Called by the audioObject holding this element. Must be present | |
655 var obj = []; | |
656 $(this.trackSliderObjects).each(function (i, trackObj) { | |
657 var node = storage.document.createElement('value'); | |
658 if (trackObj.getAttribute("interface-name") !== "null") { | |
659 node.setAttribute("interface-name", trackObj.getAttribute("interface-name")); | |
660 } | |
661 node.textContent = convSliderPosToRate(trackObj); | |
662 obj.push(node); | |
663 }); | 687 }); |
664 | 688 } |
665 return obj; | |
666 }; | |
667 this.getValue = function () { | |
668 return convSliderPosToRate(this.trackSliderObjects[0]); | |
669 }; | |
670 this.getPresentedId = function () { | |
671 return this.label; | |
672 }; | |
673 this.canMove = function () { | |
674 return true; | |
675 }; | |
676 this.error = function () { | |
677 // audioObject has an error!! | |
678 this.playback.textContent = "Error"; | |
679 $(this.playback).addClass("error-colour"); | |
680 }; | |
681 } | 689 } |
682 | 690 |
683 function outsideReferenceDOM(audioObject, index, inject) { | 691 function outsideReferenceDOM(audioObject, index, inject) { |
684 this.parent = audioObject; | 692 this.parent = audioObject; |
685 this.outsideReferenceHolder = document.createElement('div'); | 693 this.outsideReferenceHolder = document.createElement('div'); |
831 // You can use this space to add any extra nodes to your XML <audioHolder> saves | 839 // You can use this space to add any extra nodes to your XML <audioHolder> saves |
832 // Get the current <page> information in store (remember to appendChild your data to it) | 840 // Get the current <page> information in store (remember to appendChild your data to it) |
833 // pageSpecification is the current page node configuration | 841 // pageSpecification is the current page node configuration |
834 // To create new XML nodes, use storage.document.createElement(); | 842 // To create new XML nodes, use storage.document.createElement(); |
835 | 843 |
836 if (interfaceContext.interfaceSliders.length == 1) { | 844 APE.pageXMLSave(store, pageSpecification); |
837 // If there is only one axis, there only needs to be one metric return | |
838 return; | |
839 } | |
840 var audioelements = store.getElementsByTagName("audioelement"); | |
841 for (var i = 0; i < audioelements.length; i++) { | |
842 // Have to append the metric specific nodes | |
843 if (pageSpecification.outsideReference === undefined || pageSpecification.outsideReference.id != audioelements[i].id) { | |
844 var inject = audioelements[i].getElementsByTagName("metric"); | |
845 if (inject.length === 0) { | |
846 inject = storage.document.createElement("metric"); | |
847 } else { | |
848 inject = inject[0]; | |
849 } | |
850 for (var k = 0; k < interfaceContext.interfaceSliders.length; k++) { | |
851 var mrnodes = interfaceContext.interfaceSliders[k].metrics[i].exportXMLDOM(inject); | |
852 for (var j = 0; j < mrnodes.length; j++) { | |
853 var name = mrnodes[j].getAttribute("name"); | |
854 if (name == "elementTracker" || name == "elementTrackerFull" || name == "elementInitialPosition" || name == "elementFlagMoved") { | |
855 if (interfaceContext.interfaceSliders[k].name !== null) { | |
856 mrnodes[j].setAttribute("interface-name", interfaceContext.interfaceSliders[k].name); | |
857 } | |
858 mrnodes[j].setAttribute("interface-id", k); | |
859 } | |
860 } | |
861 } | |
862 } | |
863 } | |
864 } | 845 } |