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