n@619: /** n@619: * WAET Blank Template n@619: * Use this to start building your custom interface n@619: */ n@619: n@619: // Once this is loaded and parsed, begin execution n@619: loadInterface(); n@619: n@619: function loadInterface() { n@619: // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, n@619: // holding div's, or setting up any nodes which are present for the entire test sequence n@619: n@621: interfaceContext.insertPoint.innerHTML = null; // Clear the current schema n@621: n@619: // Custom comparator Object n@619: Interface.prototype.comparator = null; n@619: n@619: // The injection point into the HTML page n@619: interfaceContext.insertPoint = document.getElementById("topLevelBody"); n@619: var testContent = document.createElement('div'); n@619: testContent.id = 'testContent'; n@619: n@619: // Create the top div for the Title element n@619: var titleAttr = specification.title; n@619: var title = document.createElement('div'); n@619: title.className = "title"; n@619: title.align = "center"; n@619: var titleSpan = document.createElement('span'); n@619: n@619: // Set title to that defined in XML, else set to default n@619: if (titleAttr != undefined) { n@619: titleSpan.textContent = titleAttr; n@619: } else { n@619: titleSpan.textContent = 'Listening test'; n@619: } n@619: // Insert the titleSpan element into the title div element. n@619: title.appendChild(titleSpan); n@619: n@619: var pagetitle = document.createElement('div'); n@619: pagetitle.className = "pageTitle"; n@619: pagetitle.align = "center"; n@619: var titleSpan = document.createElement('span'); n@619: titleSpan.id = "pageTitle"; n@619: pagetitle.appendChild(titleSpan); n@619: n@619: // Create Interface buttons! n@619: var interfaceButtons = document.createElement('div'); n@619: interfaceButtons.id = 'interface-buttons'; n@619: interfaceButtons.style.height = '25px'; n@619: n@619: // Create playback start/stop points n@619: var playback = document.createElement("button"); n@619: playback.innerHTML = 'Stop'; n@619: playback.id = 'playback-button'; n@619: playback.style.float = 'left'; n@619: // onclick function. Check if it is playing or not, call the correct function in the n@619: // audioEngine, change the button text to reflect the next state. n@619: playback.onclick = function() { n@619: if (audioEngineContext.status == 1) { n@619: audioEngineContext.stop(); n@619: this.innerHTML = 'Stop'; n@619: var time = audioEngineContext.timer.getTestTime(); n@619: console.log('Stopped at ' + time); // DEBUG/SAFETY n@619: } n@619: }; n@619: // Append the interface buttons into the interfaceButtons object. n@619: interfaceButtons.appendChild(playback); n@619: n@619: // Global parent for the comment boxes on the page n@619: var feedbackHolder = document.createElement('div'); n@619: feedbackHolder.id = 'feedbackHolder'; n@619: n@619: // Construct the AB Boxes n@619: var boxes = document.createElement('div'); n@619: boxes.align = "center"; n@619: boxes.id = "box-holders"; n@619: boxes.style.float = "left"; n@619: n@619: var submit = document.createElement('button'); n@619: submit.id = "submit"; n@619: submit.onclick = buttonSubmitClick; n@619: submit.className = "big-button"; n@619: submit.textContent = "submit"; n@619: submit.style.position = "relative"; n@619: submit.style.left = (window.innerWidth-250)/2 + 'px'; n@619: n@619: feedbackHolder.appendChild(boxes); n@619: n@619: // Inject into HTML n@619: testContent.appendChild(title); // Insert the title n@619: testContent.appendChild(pagetitle); n@619: testContent.appendChild(interfaceButtons); n@619: testContent.appendChild(feedbackHolder); n@619: testContent.appendChild(submit); n@619: interfaceContext.insertPoint.appendChild(testContent); n@619: n@619: // Load the full interface n@619: testState.initialise(); n@619: testState.advanceState(); n@619: }; n@619: n@619: function loadTest(page) n@619: { n@619: // Called each time a new test page is to be build. The page specification node is the only item passed in n@621: document.getElementById('box-holders').innerHTML = null; n@621: n@621: var interfaceObj = page.interfaces; n@621: if (interfaceObj.length > 1) n@621: { n@621: console.log("WARNING - This interface only supports one node per page. Using first interface node"); n@621: } n@621: interfaceObj = interfaceObj[0]; n@621: n@621: if(interfaceObj.title != null) n@621: { n@621: document.getElementById("pageTitle").textContent = interfaceObj.title; n@621: } n@621: n@621: var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); n@621: for (var option of interfaceOptions) n@621: { n@621: if (option.type == "show") n@621: { n@621: switch(option.name) { n@621: case "playhead": n@621: var playbackHolder = document.getElementById('playback-holder'); n@621: if (playbackHolder == null) n@621: { n@621: playbackHolder = document.createElement('div'); n@621: playbackHolder.style.width = "100%"; n@621: playbackHolder.style.float = "left"; n@621: playbackHolder.align = 'center'; n@621: playbackHolder.appendChild(interfaceContext.playhead.object); n@621: feedbackHolder.appendChild(playbackHolder); n@621: } n@621: break; n@621: case "page-count": n@621: var pagecountHolder = document.getElementById('page-count'); n@621: if (pagecountHolder == null) n@621: { n@621: pagecountHolder = document.createElement('div'); n@621: pagecountHolder.id = 'page-count'; n@621: } n@621: pagecountHolder.innerHTML = 'Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+''; n@621: var inject = document.getElementById('interface-buttons'); n@621: inject.appendChild(pagecountHolder); n@621: break; n@621: case "volume": n@621: if (document.getElementById('master-volume-holder') == null) n@621: { n@621: feedbackHolder.appendChild(interfaceContext.volume.object); n@621: } n@621: break; n@621: } n@621: } n@621: } n@621: n@619: interfaceContext.comparator = new comparator(page); n@621: resizeWindow(null); n@619: } n@619: n@619: function comparator(page) n@619: { n@619: // Build prototype constructor n@619: this.interfaceObject = function(element,label) n@619: { n@619: // An example node, you can make this however you want for each audioElement. n@619: // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following n@619: // You attach them by calling audioObject.bindInterface( ) n@619: this.parent = element; n@619: this.id = element.id; n@619: this.value = 0; n@619: this.disabled = true; n@619: this.box = document.createElement('div'); n@619: this.box.className = 'comparator-holder'; n@619: this.box.setAttribute('track-id',element.id); n@619: this.box.id = 'comparator-'+label; n@619: this.selector = document.createElement('div'); n@619: this.selector.className = 'comparator-selector disabled'; n@619: var selectorText = document.createElement('span'); n@619: selectorText.textContent = label; n@619: this.selector.appendChild(selectorText); n@619: this.playback = document.createElement('button'); n@619: this.playback.className = 'comparator-button'; n@619: this.playback.disabled = true; n@619: this.playback.textContent = "Listen"; n@619: this.box.appendChild(this.selector); n@619: this.box.appendChild(this.playback); n@619: this.selector.onclick = function(event) n@619: { n@619: var label = event.currentTarget.children[0].textContent; n@619: if (label == "X" || label == "x") {return;} n@619: var time = audioEngineContext.timer.getTestTime(); n@619: if ($(event.currentTarget).hasClass('disabled')) n@619: { n@619: console.log("Please wait until sample has loaded"); n@619: return; n@619: } n@619: if (audioEngineContext.status == 0) n@619: { n@619: alert("Please listen to the samples before making a selection"); n@619: console.log("Please listen to the samples before making a selection"); n@619: return; n@619: } n@619: var id = event.currentTarget.parentElement.getAttribute('track-id'); n@619: interfaceContext.comparator.selected = id; n@619: if ($(event.currentTarget).hasClass("selected")) { n@619: $(".comparator-selector").removeClass('selected'); n@619: for (var i=0; i node. n@619: // If there is no value node (such as outside reference), return null n@619: // 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 n@619: // Use storage.document.createElement('value'); to generate the XML node. n@619: var node = storage.document.createElement('value'); n@619: node.textContent = this.value; n@619: return node; n@619: n@619: }; n@619: this.error = function() { n@619: // If there is an error with the audioObject, this will be called to indicate a failure n@619: } n@619: }; n@619: // Ensure there are only two comparisons per page n@619: if (page.audioElements.length != 2) { n@619: console.error('FATAL - There must be 2 nodes on each : '+page.id); n@619: return; n@619: } n@619: // Build the three audio elements n@619: this.pair = []; n@619: this.X = null; n@619: this.boxHolders = document.getElementById('box-holders'); n@619: for (var index=0; index saves n@619: // Get the current information in store (remember to appendChild your data to it) n@619: // pageSpecification is the current page node configuration n@619: // To create new XML nodes, use storage.document.createElement(); n@619: }