Mercurial > hg > webaudioevaluationtool
changeset 383:38439b21d369 Dev_main
STASH: UNSTABLE. Implementing APE multiple sliders.
author | Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk> |
---|---|
date | Tue, 08 Dec 2015 12:01:48 +0000 |
parents | b1cb28c63a19 |
children | b96fc647f383 |
files | ape.css ape.js core.js example_eval/project.xml |
diffstat | 4 files changed, 174 insertions(+), 138 deletions(-) [+] |
line wrap: on
line diff
--- a/ape.css Mon Dec 07 18:42:36 2015 +0000 +++ b/ape.css Tue Dec 08 12:01:48 2015 +0000 @@ -14,7 +14,8 @@ div.pageTitle { width: auto; height: 20px; - margin-top: 20px; + margin-top: 5px; + margin-bottom: 10px; } div.pageTitle span{ @@ -27,7 +28,7 @@ background-color: #ddd } -div#slider { +div.slider { /* Specify any structure for the slider holder interface */ background-color: #eee; height: 150px;
--- a/ape.js Mon Dec 07 18:42:36 2015 +0000 +++ b/ape.js Tue Dec 08 12:01:48 2015 +0000 @@ -147,33 +147,34 @@ var audioObjs = audioEngineContext.audioObjects; var audioHolder = testState.stateMap[testState.stateIndex]; var interfaces = audioHolder.interfaces; - - var minRanking = audioObjs[0].interfaceDOM.getValue(); - var maxRanking = minRanking; - - var minScale; - var maxScale; - for (var i=0; i<interfaces[0].options.length; i++) + for (var i=0; i<interfaces.length; i++) { - if (interfaces[0].options[i].check == "scalerange") { - minScale = interfaces[0].options[i].min; - maxScale = interfaces[0].options[i].max; + var minRanking = convSliderPosToRate(audioObjs[0].interfaceDOM.trackSliderObjects[i]); + var maxRanking = minRanking; + + var minScale; + var maxScale; + for (var j=0; j<interfaces[i].options.length; j++) + { + if (interfaces[i].options[j].check == "scalerange") { + minScale = interfaces[i].options[j].min; + maxScale = interfaces[i].options[j].max; + break; + } + } + for (var j=1; j<audioObjs.length; j++){ + if (audioObjs[j].specification.type != 'outsidereference') { + var ranking = convSliderPosToRate(audioObjs[j].interfaceDOM.trackSliderObjects[i]); + if (ranking < minRanking) { minRanking = ranking;} + if (ranking > maxRanking) { maxRanking = ranking;} + } + } + if (minRanking > minScale || maxRanking < maxScale) { + alert('Please use the full width of the scale'); + return false; } } - - for (var i=1; i<audioObjs.length; i++){ - if (audioObjs[i].specification.type != 'outsidereference') { - var ranking = audioObjs[i].interfaceDOM.getValue(); - if (ranking < minRanking) { minRanking = ranking;} - if (ranking > maxRanking) { maxRanking = ranking;} - } - } - if (minRanking > minScale || maxRanking < maxScale) { - alert('Please use the full width of the scale'); - return false; - } else { - return true; - } + return true; }; Interface.prototype.objectSelected = null; @@ -225,13 +226,6 @@ // Insert the titleSpan element into the title div element. title.appendChild(titleSpan); - var pagetitle = document.createElement('div'); - pagetitle.className = "pageTitle"; - pagetitle.align = "center"; - var titleSpan = document.createElement('span'); - titleSpan.id = "pageTitle"; - pagetitle.appendChild(titleSpan); - // Create Interface buttons! var interfaceButtons = document.createElement('div'); interfaceButtons.id = 'interface-buttons'; @@ -259,38 +253,9 @@ interfaceButtons.appendChild(playback); interfaceButtons.appendChild(submit); - // Now create the slider and HTML5 canvas boxes + var sliderHolder = document.createElement("div"); + sliderHolder.id = "slider-holder"; - // Create the div box to center align - var sliderBox = document.createElement('div'); - sliderBox.className = 'sliderCanvasDiv'; - sliderBox.id = 'sliderCanvasHolder'; - - // Create the slider box to hold the slider elements - var canvas = document.createElement('div'); - canvas.id = 'slider'; - canvas.align = "left"; - canvas.addEventListener('dragover',function(event){ - event.preventDefault(); - event.dataTransfer.effectAllowed = 'none'; - event.dataTransfer.dropEffect = 'copy'; - return false; - },false); - var sliderMargin = document.createAttribute('marginsize'); - sliderMargin.nodeValue = 42; // Set default margins to 42px either side - // Must have a known EXACT width, as this is used later to determine the ratings - var w = (Number(sliderMargin.nodeValue)+8)*2; - canvas.style.width = width - w +"px"; - canvas.style.marginLeft = sliderMargin.nodeValue +'px'; - canvas.setAttributeNode(sliderMargin); - sliderBox.appendChild(canvas); - - // Create the div to hold any scale objects - var scale = document.createElement('div'); - scale.className = 'sliderScale'; - scale.id = 'sliderScaleHolder'; - scale.align = 'left'; - sliderBox.appendChild(scale); // Global parent for the comment boxes on the page var feedbackHolder = document.createElement('div'); @@ -301,9 +266,8 @@ // Inject into HTML testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); testContent.appendChild(interfaceButtons); - testContent.appendChild(sliderBox); + testContent.appendChild(sliderHolder); testContent.appendChild(feedbackHolder); interfaceContext.insertPoint.appendChild(testContent); @@ -315,16 +279,78 @@ function loadTest(audioHolderObject) { - + var width = window.innerWidth; + var height = window.innerHeight; var id = audioHolderObject.id; var feedbackHolder = document.getElementById('feedbackHolder'); - var canvas = document.getElementById('slider'); + var sliderHolder = document.getElementById('slider-holder'); feedbackHolder.innerHTML = null; - canvas.innerHTML = null; + sliderHolder.innerHTML = null; var interfaceObj = audioHolderObject.interfaces; for (var k=0; k<interfaceObj.length; k++) { + // Create the div box to center align + var sliderBox = document.createElement('div'); + sliderBox.className = 'sliderCanvasDiv'; + sliderBox.id = 'sliderCanvasHolder-'+k; + + var pagetitle = document.createElement('div'); + pagetitle.className = "pageTitle"; + pagetitle.align = "center"; + var titleSpan = document.createElement('span'); + titleSpan.id = "pageTitle-"+k; + if (interfaceObj[k].title != undefined && typeof interfaceObj[k].title == "string") + { + titleSpan.textContent = interfaceObj[k].title; + } + pagetitle.appendChild(titleSpan); + sliderBox.appendChild(pagetitle); + + // Create the slider box to hold the slider elements + var canvas = document.createElement('div'); + if (interfaceObj[k].name != undefined) + canvas.id = 'slider-'+name; + else + canvas.id = 'slider-'+k; + canvas.className = 'slider'; + canvas.align = "left"; + canvas.addEventListener('dragover',function(event){ + event.preventDefault(); + event.dataTransfer.effectAllowed = 'none'; + event.dataTransfer.dropEffect = 'copy'; + return false; + },false); + var sliderMargin = document.createAttribute('marginsize'); + sliderMargin.nodeValue = 42; // Set default margins to 42px either side + // Must have a known EXACT width, as this is used later to determine the ratings + var w = (Number(sliderMargin.nodeValue)+8)*2; + canvas.style.width = width - w +"px"; + canvas.style.marginLeft = sliderMargin.nodeValue +'px'; + canvas.setAttributeNode(sliderMargin); + sliderBox.appendChild(canvas); + + // Create the div to hold any scale objects + var scale = document.createElement('div'); + scale.className = 'sliderScale'; + scale.id = 'sliderScaleHolder'; + scale.align = 'left'; + sliderBox.appendChild(scale); + sliderHolder.appendChild(sliderBox); + var positionScale = canvas.style.width.substr(0,canvas.style.width.length-2); + var offset = Number(canvas.attributes['marginsize'].value); + $(interfaceObj[k].scale).each(function(index,scaleObj){ + var value = document.createAttribute('value'); + var position = Number(scaleObj[0])*0.01; + value.nodeValue = position; + var pixelPosition = (position*positionScale)+offset; + var scaleDOM = document.createElement('span'); + scaleDOM.textContent = scaleObj[1]; + scale.appendChild(scaleDOM); + scaleDOM.style.left = Math.floor((pixelPosition-($(scaleDOM).width()/2)))+'px'; + scaleDOM.setAttributeNode(value); + }); + for (var i=0; i<interfaceObj[k].options.length; i++) { if (interfaceObj[k].options[i].type == 'option' && interfaceObj[k].options[i].name == 'playhead') @@ -352,36 +378,8 @@ } } } - // Setup question title var commentBoxPrefix = "Comment on track"; - if (interfaceObj.length != 0) { - interfaceObj = interfaceObj[0]; - var titleNode = interfaceObj.title; - if (titleNode != undefined) - { - document.getElementById('pageTitle').textContent = titleNode; - } - var positionScale = canvas.style.width.substr(0,canvas.style.width.length-2); - var offset = Number(document.getElementById('slider').attributes['marginsize'].value); - var scale = document.getElementById('sliderScaleHolder'); - scale.innerHTML = null; - $(interfaceObj.scale).each(function(index,scaleObj){ - var value = document.createAttribute('value'); - var position = Number(scaleObj[0])*0.01; - value.nodeValue = position; - var pixelPosition = (position*positionScale)+offset; - var scaleDOM = document.createElement('span'); - scaleDOM.textContent = scaleObj[1]; - scale.appendChild(scaleDOM); - scaleDOM.style.left = Math.floor((pixelPosition-($(scaleDOM).width()/2)))+'px'; - scaleDOM.setAttributeNode(value); - }); - - if (interfaceObj.commentBoxPrefix != undefined) { - commentBoxPrefix = interfaceObj.commentBoxPrefix; - } - } var commentShow = audioHolderObject.elementComments; @@ -403,20 +401,11 @@ var node = interfaceContext.createCommentBox(audioObject); // Create a slider per track - audioObject.interfaceDOM = new sliderObject(audioObject); + audioObject.interfaceDOM = new sliderObject(audioObject,interfaceObj); if (audioObject.state == 1) { audioObject.interfaceDOM.enable(); } - - // Distribute it randomnly - var w = window.innerWidth - (offset+8)*2; - w = Math.random()*w; - w = Math.floor(w+(offset+8)); - audioObject.interfaceDOM.trackSliderObj.style.left = w+'px'; - - canvas.appendChild(audioObject.interfaceDOM.trackSliderObj); - audioObject.metric.initialised(convSliderPosToRate(audioObject.interfaceDOM.trackSliderObj)); }); @@ -428,7 +417,7 @@ event.preventDefault(); }); - $('#slider').mousemove(function(event) { + $('.slider').mousemove(function(event) { event.preventDefault(); var obj = interfaceContext.getSelectedObject(); if (obj == null) {return;} @@ -454,9 +443,10 @@ audioEngineContext.play(id); // Currently playing track red, rest green - //document.getElementById('track-slider-'+index).style.backgroundColor = "#FF0000"; + $('.track-slider').removeClass('track-slider-playing'); - $(obj).addClass('track-slider-playing'); + var name = ".track-slider-"+obj.getAttribute("trackindex"); + $(name).addClass('track-slider-playing'); $('.comment-div').removeClass('comment-box-playing'); $('#comment-div-'+id).addClass('comment-box-playing'); var outsideReference = document.getElementById('outside-reference'); @@ -505,30 +495,55 @@ //testWaitIndicator(); } -function sliderObject(audioObject) { +function sliderObject(audioObject,interfaceObjects) { // Create a new slider object; this.parent = audioObject; - this.trackSliderObj = document.createElement('div'); - this.trackSliderObj.className = 'track-slider track-slider-disabled'; - this.trackSliderObj.id = 'track-slider-'+audioObject.id; - - this.trackSliderObj.setAttribute('trackIndex',audioObject.id); - this.trackSliderObj.innerHTML = '<span>'+audioObject.id+'</span>'; + this.trackSliderObjects = []; + for (var i=0; i<interfaceObjects.length; i++) + { + var trackObj = document.createElement('div'); + trackObj.className = 'track-slider track-slider-disabled track-slider-'+audioObject.id; + trackObj.id = 'track-slider-'+i+'-'+audioObject.id; + trackObj.setAttribute('trackIndex',audioObject.id); + trackObj.innerHTML = '<span>'+audioObject.id+'</span>'; + if (interfaceObjects[i].name != undefined) { + trackObj.setAttribute('interface-name',interfaceObjects[i].name); + } else { + trackObj.setAttribute('interface-name',i); + } + this.trackSliderObjects.push(trackObj); + var slider = document.getElementById("slider-"+trackObj.getAttribute("interface-name")); + var offset = Number(slider.attributes['marginsize'].value); + // Distribute it randomnly + var w = window.innerWidth - (offset+8)*2; + w = Math.random()*w; + w = Math.floor(w+(offset+8)); + trackObj.style.left = w+'px'; + slider.appendChild(trackObj); + } // Onclick, switch playback to that track this.enable = function() { if (this.parent.state == 1) { - $(this.trackSliderObj).removeClass('track-slider-disabled'); + $(this.trackSliderObjects).each(function(i,trackObj){ + $(trackObj).removeClass('track-slider-disabled'); + }); } }; this.exportXMLDOM = function(audioObject) { // Called by the audioObject holding this element. Must be present - var node = document.createElement('value'); - node.textContent = convSliderPosToRate(this.trackSliderObj); - return node; + var obj = []; + $(this.trackSliderObjects).each(function(i,trackObj){ + var node = document.createElement('value'); + node.setAttribute("name",trackObj.getAttribute("interface-name")); + node.textContent = convSliderPosToRate(trackObj); + obj.push(node); + }); + + return obj; }; this.getValue = function() { return convSliderPosToRate(this.trackSliderObj); @@ -596,12 +611,13 @@ } } -function convSliderPosToRate(slider) +function convSliderPosToRate(trackSlider) { - var w = document.getElementById('slider').style.width; - var marginsize = Number(document.getElementById('slider').attributes['marginsize'].value); + var slider = trackSlider.parentElement; + var w = slider.style.width; + var marginsize = Number(slider.attributes['marginsize'].value); var maxPix = w.substr(0,w.length-2); - var pix = slider.style.left; + var pix = trackSlider.style.left; pix = pix.substr(0,pix.length-2); var rate = (pix-marginsize)/maxPix; return rate;
--- a/core.js Mon Dec 07 18:42:36 2015 +0000 +++ b/core.js Tue Dec 08 12:01:48 2015 +0000 @@ -649,7 +649,6 @@ this.testPageCompleted = function(store, testXML, testId) { // Function called each time a test page has been completed - // Can be used to over-rule default behaviour var metric = document.createElement('metric'); if (audioEngineContext.metric.enableTestTimer) { @@ -658,17 +657,17 @@ testTime.textContent = audioEngineContext.timer.testDuration; metric.appendChild(testTime); } - testXML.appendChild(metric); + store.appendChild(metric); var audioObjects = audioEngineContext.audioObjects; for (var i=0; i<audioObjects.length; i++) { var audioElement = audioEngineContext.audioObjects[i].exportXMLDOM(); audioElement.setAttribute('presentedId',i); - testXML.appendChild(audioElement); + store.appendChild(audioElement); } $(interfaceContext.commentQuestions).each(function(index,element){ var node = element.exportXMLDOM(); - testXML.appendChild(node); + store.appendChild(node); }); pageXMLSave(store, testXML); }; @@ -914,10 +913,10 @@ var maxId; for (var i=0; i<this.audioObjects.length; i++) { - lens.push(this.audioObjects[i].buffer.length); - if (length < this.audioObjects[i].buffer.length) + lens.push(this.audioObjects[i].buffer.buffer.length); + if (length < this.audioObjects[i].buffer.buffer.length) { - length = this.audioObjects[i].buffer.length; + length = this.audioObjects[i].buffer.buffer.length; maxId = i; } } @@ -929,7 +928,7 @@ // Extract the audio and zero-pad for (var i=0; i<lens.length; i++) { - var orig = this.audioObjects[i].buffer; + var orig = this.audioObjects[i].buffer.buffer; var hold = audioContext.createBuffer(orig.numberOfChannels,length,orig.sampleRate); for (var c=0; c<orig.numberOfChannels; c++) { @@ -938,7 +937,7 @@ for (var n=0; n<orig.length; n++) {inData[n] = outData[n];} } - this.audioObjects[i].buffer = hold; + this.audioObjects[i].buffer.buffer = hold; delete orig; } }; @@ -1077,7 +1076,15 @@ file.setAttribute('duration',this.buffer.duration); root.appendChild(file); if (this.specification.type != 'outsidereference') { - root.appendChild(this.interfaceDOM.exportXMLDOM(this)); + var interfaceXML = this.interfaceDOM.exportXMLDOM(this); + if (interfaceXML.length == undefined) { + root.appendChild(); + } else { + for (var i=0; i<interfaceXML.length; i++) + { + root.appendChild(interfaceXML[i]); + } + } root.appendChild(this.commentDOM.exportXMLDOM(this)); if(this.specification.type == 'anchor') { root.setAttribute('anchor',true); @@ -1503,6 +1510,7 @@ } this.commonInterface = new function() { + this.name = undefined; this.OptionNode = function(child) { this.type = child.nodeName; if (this.type == 'option') @@ -1536,6 +1544,10 @@ }; this.options = []; if (commonInterfaceNode != undefined) { + var name = commonInterfaceNode.getAttribute("name"); + if (name != undefined) { + this.name = name; + } var child = commonInterfaceNode.firstElementChild; while (child != undefined) { this.options.push(new this.OptionNode(child));
--- a/example_eval/project.xml Mon Dec 07 18:42:36 2015 +0000 +++ b/example_eval/project.xml Tue Dec 08 12:01:48 2015 +0000 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <BrowserEvalProjectDocument> - <setup interface="APE" projectReturn="save.php" randomiseOrder='true' collectMetrics='true' testPages="2"> + <setup interface="APE" projectReturn="save.php" randomiseOrder='false' collectMetrics='true' testPages="2"> <PreTest> <question id="Location" mandatory="true" boxsize="large">Please enter your location.</question> <checkbox id="experience"> @@ -42,14 +42,21 @@ </interface> </setup> <audioHolder id='test-0' hostURL="example_eval/" sampleRate="44100" randomiseOrder='true' repeatCount='0' loop='true' elementComments='true'> - <interface> - <title>Example Test Question</title> + <interface name="preference"> + <title>Preference</title> <scale position="0">Min</scale> <scale position="100">Max</scale> <scale position="50">Middle</scale> <scale position="20">20</scale> <commentBoxPrefix>Comment on fragment</commentBoxPrefix> </interface> + <interface name="depth"> + <title>Depth</title> + <scale position="0">Low</scale> + <scale position="100">High</scale> + <scale position="50">Middle</scale> + <commentBoxPrefix>Comment on fragment</commentBoxPrefix> + </interface> <audioElements url="0.wav" id="0" type="anchor"/> <audioElements url="1.wav" id="1"/> <audioElements url="2.wav" id="2"/>