Mercurial > hg > webaudioevaluationtool
changeset 2538:464c6c6692d6
Beautified entire project.
line wrap: on
line diff
--- a/analysis/analysis.css Mon Nov 14 12:11:38 2016 +0000 +++ b/analysis/analysis.css Mon Nov 14 14:17:03 2016 +0000 @@ -5,12 +5,12 @@ div.code { margin: 5px; padding-left: 15px; - background-color: rgb(200,200,200); + background-color: rgb(200, 200, 200); border: 2px dashed black; } -table td tr{ +table td tr { padding: 5px; } -div.filter-entry{ +div.filter-entry { padding: 5px; -} \ No newline at end of file +}
--- a/analysis/analysis.js Mon Nov 14 12:11:38 2016 +0000 +++ b/analysis/analysis.js Mon Nov 14 14:17:03 2016 +0000 @@ -1,31 +1,26 @@ /* -* Analysis script for WAET -*/ + * Analysis script for WAET + */ // Firefox does not have an XMLDocument.prototype.getElementsByName // and there is no searchAll style command, this custom function will // search all children recusrively for the name. Used for XSD where all // element nodes must have a name and therefore can pull the schema node -XMLDocument.prototype.getAllElementsByName = function(name) -{ +XMLDocument.prototype.getAllElementsByName = function (name) { name = String(name); var selected = this.documentElement.getAllElementsByName(name); return selected; } -Element.prototype.getAllElementsByName = function(name) -{ +Element.prototype.getAllElementsByName = function (name) { name = String(name); var selected = []; var node = this.firstElementChild; - while(node != null) - { - if (node.getAttribute('name') == name) - { + while (node != null) { + if (node.getAttribute('name') == name) { selected.push(node); } - if (node.childElementCount > 0) - { + if (node.childElementCount > 0) { selected = selected.concat(node.getAllElementsByName(name)); } node = node.nextElementSibling; @@ -33,26 +28,21 @@ return selected; } -XMLDocument.prototype.getAllElementsByTagName = function(name) -{ +XMLDocument.prototype.getAllElementsByTagName = function (name) { name = String(name); var selected = this.documentElement.getAllElementsByTagName(name); return selected; } -Element.prototype.getAllElementsByTagName = function(name) -{ +Element.prototype.getAllElementsByTagName = function (name) { name = String(name); var selected = []; var node = this.firstElementChild; - while(node != null) - { - if (node.nodeName == name) - { + while (node != null) { + if (node.nodeName == name) { selected.push(node); } - if (node.childElementCount > 0) - { + if (node.childElementCount > 0) { selected = selected.concat(node.getAllElementsByTagName(name)); } node = node.nextElementSibling; @@ -62,15 +52,12 @@ // Firefox does not have an XMLDocument.prototype.getElementsByName if (typeof XMLDocument.prototype.getElementsByName != "function") { - XMLDocument.prototype.getElementsByName = function(name) - { + XMLDocument.prototype.getElementsByName = function (name) { name = String(name); var node = this.documentElement.firstElementChild; var selected = []; - while(node != null) - { - if (node.getAttribute('name') == name) - { + while (node != null) { + if (node.getAttribute('name') == name) { selected.push(node); } node = node.nextElementSibling; @@ -80,41 +67,42 @@ } var chartContext, testData; -window.onload = function() { +window.onload = function () { // Load the Visualization API and the corechart package. - google.charts.load('current', {'packages':['corechart']}); + google.charts.load('current', { + 'packages': ['corechart'] + }); chartContext = new Chart(); testData = new Data(); } function get(url) { - // Return a new promise. - return new Promise(function(resolve, reject) { - // Do the usual XHR stuff - var req = new XMLHttpRequest(); - req.open('GET', url); - req.onload = function() { - // This is called even on 404 etc - // so check the status - if (req.status == 200) { - // Resolve the promise with the response text - resolve(req.response); - } - else { - // Otherwise reject with the status text - // which will hopefully be a meaningful error - reject(Error(req.statusText)); - } - }; + // Return a new promise. + return new Promise(function (resolve, reject) { + // Do the usual XHR stuff + var req = new XMLHttpRequest(); + req.open('GET', url); + req.onload = function () { + // This is called even on 404 etc + // so check the status + if (req.status == 200) { + // Resolve the promise with the response text + resolve(req.response); + } else { + // Otherwise reject with the status text + // which will hopefully be a meaningful error + reject(Error(req.statusText)); + } + }; - // Handle network errors - req.onerror = function() { - reject(Error("Network Error")); - }; + // Handle network errors + req.onerror = function () { + reject(Error("Network Error")); + }; - // Make the request - req.send(); - }); + // Make the request + req.send(); + }); } function arrayMean(values) { @@ -128,15 +116,17 @@ function percentile(values, p) { //http://web.stanford.edu/class/archive/anthsci/anthsci192/anthsci192.1064/handouts/calculating%20percentiles.pdf - values.sort( function(a,b) {return a - b;} ); + values.sort(function (a, b) { + return a - b; + }); // get ordinal rank - var index = values.length*p/100; + var index = values.length * p / 100; var k = Math.floor(index); if (k == index) { return values[k]; } else { - var f = index-k; - var x_int = (1-f)*values[k]+f*values[k+1]; + var f = index - k; + var x_int = (1 - f) * values[k] + f * values[k + 1]; return x_int; } } @@ -166,19 +156,19 @@ function boxplotRow(array) { // Take an array of element values and return array of computed intervals var result = { - median : percentile(array,50), - pct25 : percentile(array,25), - pct75 : percentile(array,75), - IQR : null, + median: percentile(array, 50), + pct25: percentile(array, 25), + pct75: percentile(array, 75), + IQR: null, min: null, max: null, outliers: new Array() } - result.IQR = result.pct75-result.pct25; + result.IQR = result.pct75 - result.pct25; var rest = []; - var pct75_IQR = result.pct75+1.5*result.IQR; - var pct25_IQR = result.pct25-1.5*result.IQR; - for (var i=0; i<array.length; i++) { + var pct75_IQR = result.pct75 + 1.5 * result.IQR; + var pct25_IQR = result.pct25 - 1.5 * result.IQR; + for (var i = 0; i < array.length; i++) { //outliers, ranger above pct75+1.5*IQR or below pct25-1.5*IQR var point = array[i]; if (point > pct75_IQR || point < pct25_IQR) { @@ -190,23 +180,27 @@ result.max = arrayMax(rest); result.min = arrayMin(rest); return result; - + } -function arrayHistogram(values,steps,min,max) { +function arrayHistogram(values, steps, min, max) { if (steps == undefined) { steps = 0.25; console.log("Warning: arrayHistogram called without steps size set, default to 0.25"); } - if (min == undefined) {min = arrayMin(values);} - if (max == undefined) {max = arrayMax(values);} + if (min == undefined) { + min = arrayMin(values); + } + if (max == undefined) { + max = arrayMax(values); + } var histogram = []; var index = min; - while(index < max) { + while (index < max) { histogram.push({ marker: index, lt: index, - rt: index+steps, + rt: index + steps, count: 0 }); index += steps; @@ -225,13 +219,13 @@ function Chart() { this.valueData; this.charts = []; - - this.chartObject = function(name) { + + this.chartObject = function (name) { // Create the charting object this.name = name; this.root = document.createElement("div"); this.root.className = "chart-holder"; - this.root.setAttribute("name",name); + this.root.setAttribute("name", name); this.chartDOM = document.createElement("div"); this.tableDOM = document.createElement("div"); this.latexDOM = document.createElement("div"); @@ -242,30 +236,31 @@ this.print = document.createElement("button"); this.sortDataButton = document.createElement("button"); this.sortDataButton.textContent = "Sort by Data"; - this.sortDataButton.addEventListener("click",this); - this.sortDataButton.setAttribute("name","sort-data"); + this.sortDataButton.addEventListener("click", this); + this.sortDataButton.setAttribute("name", "sort-data"); this.sortNameButton = document.createElement("button"); this.sortNameButton.textContent = "Sort by Name"; - this.sortNameButton.addEventListener("click",this); - this.sortNameButton.setAttribute("name","sort-name"); - this.draw = function() { - if (this.chart == undefined) {return;} + this.sortNameButton.addEventListener("click", this); + this.sortNameButton.setAttribute("name", "sort-name"); + this.draw = function () { + if (this.chart == undefined) { + return; + } this.tableDOM.innerHTML = null; this.latexDOM.innerHTML = null; this.buildTable(); this.writeLatex(); - this.chart.draw(this.data,this.options); + this.chart.draw(this.data, this.options); } - this.sortData = function() { + this.sortData = function () { this.data.sort(1); } - this.sortName = function() { + this.sortName = function () { this.data.sort(0); } - this.handleEvent = function() { + this.handleEvent = function () { // Only used to handle the chart.event.addListener(this,'ready') callback - switch(event.currentTarget.getAttribute("name")) - { + switch (event.currentTarget.getAttribute("name")) { case "download": window.open(this.chart.getImageURI()); break; @@ -279,7 +274,7 @@ break; } } - + this.root.appendChild(this.chartDOM); this.root.appendChild(this.tableDOM); this.root.appendChild(this.latexDOM); @@ -287,16 +282,15 @@ this.root.appendChild(this.sortNameButton); this.root.appendChild(this.print); this.print.textContent = "Download"; - this.print.setAttribute("name","download"); - this.print.addEventListener("click",this); + this.print.setAttribute("name", "download"); + this.print.addEventListener("click", this); this.root.appendChild(this.downloadDOM); - this.buildTable = function() { + this.buildTable = function () { var table = document.createElement("table"); table.border = "1"; var numRows = this.data.getNumberOfRows(); var numColumns = this.data.getNumberOfColumns(); - for (var columnIndex=0; columnIndex<numColumns; columnIndex++) - { + for (var columnIndex = 0; columnIndex < numColumns; columnIndex++) { var tableTitle = this.data.getColumnLabel(columnIndex); if (tableTitle != "") { var table_row = document.createElement('tr'); @@ -304,13 +298,11 @@ var row_title = document.createElement('td'); table_row.appendChild(row_title); row_title.textContent = tableTitle; - for (var rowIndex=0; rowIndex<numRows; rowIndex++) - { + for (var rowIndex = 0; rowIndex < numRows; rowIndex++) { var row_entry = document.createElement('td'); table_row.appendChild(row_entry); - var entry = this.data.getValue(rowIndex,columnIndex); - if (isFinite(Number(entry))) - { + var entry = this.data.getValue(rowIndex, columnIndex); + if (isFinite(Number(entry))) { entry = String(Number(entry).toFixed(4)); } row_entry.textContent = entry; @@ -319,7 +311,7 @@ } this.tableDOM.appendChild(table); }; - this.writeLatex = function() { + this.writeLatex = function () { var numRows = this.data.getNumberOfRows(); var numColumns = this.data.getNumberOfColumns(); var root = document.createElement("div"); @@ -329,25 +321,23 @@ var start = document.createElement("p"); start.textContent = "\\" + "begin{tabular}{|l|"; holder.appendChild(start); - for (var i=0; i<numRows; i++) { - start.textContent = start.textContent+"c|"; + for (var i = 0; i < numRows; i++) { + start.textContent = start.textContent + "c|"; } start.textContent = start.textContent.concat("}"); // Now write the rows: - for (var rIndex=0; rIndex<numColumns; rIndex++) { + for (var rIndex = 0; rIndex < numColumns; rIndex++) { var tableTitle = this.data.getColumnLabel(rIndex); - if(tableTitle != "") - { + if (tableTitle != "") { var row = document.createElement("p"); row.textContent = tableTitle.concat(" & "); - for (var cIndex=0; cIndex<numRows; cIndex++) { - var entry = this.data.getValue(cIndex,rIndex); - if (isFinite(Number(entry))) - { + for (var cIndex = 0; cIndex < numRows; cIndex++) { + var entry = this.data.getValue(cIndex, rIndex); + if (isFinite(Number(entry))) { entry = String(Number(entry).toFixed(4)); } row.textContent = row.textContent.concat(entry); - if (cIndex < numRows-1) { + if (cIndex < numRows - 1) { row.textContent = row.textContent.concat(" & "); } else { row.textContent = row.textContent.concat(" \\\\ \\hline"); @@ -364,86 +354,98 @@ this.latexDOM.appendChild(root); } } - - this.clear = function() { + + this.clear = function () { var inject = document.getElementById("test-pages"); for (var chart of this.charts) { inject.removeChild(chart.root); } this.charts = []; } - - this.drawTestMean = function() { + + this.drawTestMean = function () { // This draws one bargraph per axis with every test element on if (this.valueData == null) { console.log("Error - Data not loaded"); return; } var chartList = []; - + // Create the data table for (var page of this.valueData.pages) { for (var element of page.elements) { for (var axis of element.axis) { // Find the axis - var axisChart = chartList.find(function(element,index,array){ - if (element.name == this) {return true;} else {return false;} - },"mean-test-"+axis.name); + var axisChart = chartList.find(function (element, index, array) { + if (element.name == this) { + return true; + } else { + return false; + } + }, "mean-test-" + axis.name); if (axisChart == null) { - axisChart = new this.chartObject("mean-test-"+axis.name); + axisChart = new this.chartObject("mean-test-" + axis.name); axisChart.options = { - 'title':'Mean of axis: '+axis.name, - 'width':window.innerWidth*0.9, - 'height':(window.innerWidth*0.9)/1.77 + 'title': 'Mean of axis: ' + axis.name, + 'width': window.innerWidth * 0.9, + 'height': (window.innerWidth * 0.9) / 1.77 } - axisChart.data.addColumn('string','id'); - axisChart.data.addColumn('number',axis.name); + axisChart.data.addColumn('string', 'id'); + axisChart.data.addColumn('number', axis.name); chartList.push(axisChart); document.getElementById("test-pages").appendChild(axisChart.root); } var mean = arrayMean(axis.values); - axisChart.data.addRow([element.id,mean]); + axisChart.data.addRow([element.id, mean]); } } } - + // Build and push charts for (var chart of chartList) { chart.chart = new google.visualization.ColumnChart(chart.chartDOM); - chart.chart.draw(chart.data,chart.options); + chart.chart.draw(chart.data, chart.options); chart.buildTable(); chart.writeLatex(); this.charts.push(chart); } } - - this.drawTestBoxplot = function() { + + this.drawTestBoxplot = function () { if (this.valueData == null) { console.log("Error - Data not loaded"); return; } var chartList = []; - + // Creates one chart per axis - + // Create the data table for (var page of this.valueData.pages) { for (var element of page.elements) { for (var axis of element.axis) { // Find the axis - var axisChart = chartList.find(function(element,index,array){ - if (element.name == this) {return true;} else {return false;} - },"boxplot-test-"+axis.name); + var axisChart = chartList.find(function (element, index, array) { + if (element.name == this) { + return true; + } else { + return false; + } + }, "boxplot-test-" + axis.name); if (axisChart == null) { // Axis chart doesn't exist - axisChart = new this.chartObject("boxplot-test-"+axis.name); + axisChart = new this.chartObject("boxplot-test-" + axis.name); axisChart.options = { - 'title':'Boxplot of axis '+axis.name, - 'width':window.innerWidth*0.9, - 'height':(window.innerWidth*0.9)/1.77, - legend: {position: 'none'}, + 'title': 'Boxplot of axis ' + axis.name, + 'width': window.innerWidth * 0.9, + 'height': (window.innerWidth * 0.9) / 1.77, + legend: { + position: 'none' + }, lineWidth: 0, - series: [{'color': '#D3362D'}], + series: [{ + 'color': '#D3362D' + }], intervals: { barWidth: 1, boxWidth: 1, @@ -463,32 +465,52 @@ } } }; - axisChart.data.addColumn('string','id'); - axisChart.data.addColumn('number','median'); - axisChart.data.addColumn({id:'max',type:'number',role:'interval'}); - axisChart.data.addColumn({id:'min',type:'number',role:'interval'}); - axisChart.data.addColumn({id:'firstQuartile',type:'number',role:'interval'}); - axisChart.data.addColumn({id:'median',type:'number',role:'interval'}); - axisChart.data.addColumn({id:'thirdQuartile',type:'number',role:'interval'}); + axisChart.data.addColumn('string', 'id'); + axisChart.data.addColumn('number', 'median'); + axisChart.data.addColumn({ + id: 'max', + type: 'number', + role: 'interval' + }); + axisChart.data.addColumn({ + id: 'min', + type: 'number', + role: 'interval' + }); + axisChart.data.addColumn({ + id: 'firstQuartile', + type: 'number', + role: 'interval' + }); + axisChart.data.addColumn({ + id: 'median', + type: 'number', + role: 'interval' + }); + axisChart.data.addColumn({ + id: 'thirdQuartile', + type: 'number', + role: 'interval' + }); chartList.push(axisChart); document.getElementById("test-pages").appendChild(axisChart.root); } var result = boxplotRow(axis.values); - axisChart.data.addRow([element.id,result.median,result.max,result.min,result.pct25,result.median,result.pct75]); + axisChart.data.addRow([element.id, result.median, result.max, result.min, result.pct25, result.median, result.pct75]); } } } // Build and push charts for (var chart of chartList) { chart.chart = new google.visualization.LineChart(chart.chartDOM); - chart.chart.draw(chart.data,chart.options); + chart.chart.draw(chart.data, chart.options); chart.buildTable(); chart.writeLatex(); this.charts.push(chart); } } - - this.drawPageMean = function() { + + this.drawPageMean = function () { // First we must get the value data if (this.valueData == null) { console.log("Error - Data not loaded"); @@ -496,22 +518,22 @@ } // We create one plot per page for (var page of this.valueData.pages) { - + // Create the chart resulting point - var chart = new this.chartObject("mean-page-"+page.id); + var chart = new this.chartObject("mean-page-" + page.id); document.getElementById("test-pages").appendChild(chart.root); - + // Create the data table - chart.data.addColumn('string','id'); + chart.data.addColumn('string', 'id'); // Get axis labels for (var axis of page.elements[0].axis) { - chart.data.addColumn('number',axis.name); + chart.data.addColumn('number', axis.name); } var rows = []; // Rows is an array of tuples [col1, col2, col3 ... colN]; for (var element of page.elements) { var entry = [element.id]; - for (var i=0; i<page.elements[0].axis.length; i++) { - var mean =0; + for (var i = 0; i < page.elements[0].axis.length; i++) { + var mean = 0; if (i < element.axis.length) { var axis = element.axis[i]; mean = arrayMean(axis.values); @@ -522,20 +544,20 @@ } chart.data.addRows(rows); chart.options = { - 'title':'Mean of page: '+page.id, - 'width':800, - 'height':700 - } - // Draw the chart + 'title': 'Mean of page: ' + page.id, + 'width': 800, + 'height': 700 + } + // Draw the chart chart.chart = new google.visualization.ColumnChart(chart.chartDOM); - chart.chart.draw(chart.data,chart.options); + chart.chart.draw(chart.data, chart.options); chart.buildTable(); chart.writeLatex(); this.charts.push(chart); } } - - this.drawElementHistogram = function() { + + this.drawElementHistogram = function () { // First we must get the value data if (this.valueData == null) { console.log("Error - Data not loaded"); @@ -545,18 +567,17 @@ for (var page of this.valueData.pages) { for (var element of page.elements) { // Build the chart object - var chart = new this.chartObject("histogram-element-"+element.id); + var chart = new this.chartObject("histogram-element-" + element.id); document.getElementById("test-pages").appendChild(chart.root); - chart.data.addColumn('string','index'); + chart.data.addColumn('string', 'index'); var histograms = []; for (var axis of element.axis) { - chart.data.addColumn('number',axis.name); - histograms.push(arrayHistogram(axis.values,0.125,0.0,1.0)); + chart.data.addColumn('number', axis.name); + histograms.push(arrayHistogram(axis.values, 0.125, 0.0, 1.0)); } for (var axis of element.axis) { - for (var i=0; i<histograms[0].length; i++) - { - var entry = [""+histograms[0][i].lt.toPrecision(2)+"-"+histograms[0][i].rt.toPrecision(3)] + for (var i = 0; i < histograms[0].length; i++) { + var entry = ["" + histograms[0][i].lt.toPrecision(2) + "-" + histograms[0][i].rt.toPrecision(3)] for (var histogram of histograms) { entry.push(histogram[i].count); } @@ -564,14 +585,16 @@ } } chart.options = { - 'title':'Histogram of element: '+element.id, - 'width':800, - 'height':700, - 'bar':{'groupWidth': '100%'} - } - // Draw the chart + 'title': 'Histogram of element: ' + element.id, + 'width': 800, + 'height': 700, + 'bar': { + 'groupWidth': '100%' + } + } + // Draw the chart chart.chart = new google.visualization.ColumnChart(chart.chartDOM); - chart.chart.draw(chart.data,chart.options); + chart.chart.draw(chart.data, chart.options); chart.buildTable(); chart.writeLatex(); this.charts.push(chart); @@ -582,49 +605,51 @@ function Data() { // This holds the link between the server side calculations and the client side visualisation of the data - + // Dynamically generate the test filtering / page filterting tools var self = this; // Collect the test types and counts this.testSavedDiv = document.getElementById("test-saved"); this.testSaves = null; this.selectURL = null; - + this.specification = new Specification(); - get("../xml/test-schema.xsd").then(function(response){ + get("../xml/test-schema.xsd").then(function (response) { var parse = new DOMParser(); - self.specification.schema = parse.parseFromString(response,'text/xml'); - },function(error){ + self.specification.schema = parse.parseFromString(response, 'text/xml'); + }, function (error) { console.log("ERROR: Could not get Test Schema"); }); - this.update = function(url) { + this.update = function (url) { var self = this; } - - this.updateData = function(req_str) { + + this.updateData = function (req_str) { // Now go get that data - get(req_str).then(function(response){ + get(req_str).then(function (response) { // Returns the data chartContext.valueData = JSON.parse(response); - },function(error){console.error(error);}); + }, function (error) { + console.error(error); + }); } } -var interfaceContext = new function() { +var interfaceContext = new function () { // This creates the interface for the user to connect with the dynamic back-end to retrieve data this.rootDOM = document.createElement("div"); this.getDataButton = { button: document.createElement("button"), parent: this, - handleEvent: function(event) { + handleEvent: function (event) { // Get the list of files: - var req_str = "../php/get_filtered_score.php"+this.parent.getFilterString(); + var req_str = "../php/get_filtered_score.php" + this.parent.getFilterString(); testData.updateData(req_str); } } this.getDataButton.button.textContent = "Get Filtered Data"; - this.getDataButton.button.addEventListener("click",this.getDataButton); - + this.getDataButton.button.addEventListener("click", this.getDataButton); + this.getRawScoreData = { root: document.createElement("div"), csvDOM: document.createElement("button"), @@ -633,36 +658,42 @@ presentDOM: document.createElement("div"), parent: this, XHR: new XMLHttpRequest(), - handleEvent: function(event) { + handleEvent: function (event) { this.presentDOM.innerHTML = null; - var url = "../php/get_filtered_score.php"+this.parent.getFilterString(); - this.XHR.open("GET",url+"&format="+event.currentTarget.textContent,true); - switch(event.currentTarget.textContent) { + var url = "../php/get_filtered_score.php" + this.parent.getFilterString(); + this.XHR.open("GET", url + "&format=" + event.currentTarget.textContent, true); + switch (event.currentTarget.textContent) { case "CSV": - this.XHR.onload = function() { + this.XHR.onload = function () { var file = [this.response]; - var bb = new Blob(file,{type: 'text/csv'}); - this.parent.presentDOM.appendChild( this.parent.generateLink(bb,"scores.csv") ); + var bb = new Blob(file, { + type: 'text/csv' + }); + this.parent.presentDOM.appendChild(this.parent.generateLink(bb, "scores.csv")); } break; case "JSON": - this.XHR.onload = function() { + this.XHR.onload = function () { var file = [this.response]; - var bb = new Blob(file,{type: 'application/json'}); - this.parent.presentDOM.appendChild( this.parent.generateLink(bb,"scores.json") ); + var bb = new Blob(file, { + type: 'application/json' + }); + this.parent.presentDOM.appendChild(this.parent.generateLink(bb, "scores.json")); } break; case "XML": - this.XHR.onload = function() { + this.XHR.onload = function () { var file = [this.response]; - var bb = new Blob(file,{type: 'text/xml'}); - this.parent.presentDOM.appendChild( this.parent.generateLink(bb,"scores.xml") ); + var bb = new Blob(file, { + type: 'text/xml' + }); + this.parent.presentDOM.appendChild(this.parent.generateLink(bb, "scores.xml")); } break; } this.XHR.send(); }, - generateLink: function(blob,filename) { + generateLink: function (blob, filename) { var dnlk = window.URL.createObjectURL(blob); var a = document.createElement("a"); a.hidden = ''; @@ -672,28 +703,28 @@ return a; } } - + this.getRawScoreData.root.appendChild(this.getRawScoreData.csvDOM); this.getRawScoreData.root.appendChild(this.getRawScoreData.jsonDOM); this.getRawScoreData.root.appendChild(this.getRawScoreData.xmlDOM); this.getRawScoreData.root.appendChild(this.getRawScoreData.presentDOM); this.getRawScoreData.XHR.parent = this.getRawScoreData; this.getRawScoreData.csvDOM.textContent = 'CSV'; - this.getRawScoreData.csvDOM.addEventListener('click',this.getRawScoreData); + this.getRawScoreData.csvDOM.addEventListener('click', this.getRawScoreData); this.getRawScoreData.jsonDOM.textContent = 'JSON'; - this.getRawScoreData.jsonDOM.addEventListener('click',this.getRawScoreData); + this.getRawScoreData.jsonDOM.addEventListener('click', this.getRawScoreData); this.getRawScoreData.xmlDOM.textContent = 'XML'; - this.getRawScoreData.xmlDOM.addEventListener('click',this.getRawScoreData); - + this.getRawScoreData.xmlDOM.addEventListener('click', this.getRawScoreData); + this.testSaves = { json: null, selectedURL: null, inputs: [], parent: this }; - this.init = function() { + this.init = function () { var self = this; - get('../php/get_tests.php?format=JSON').then(function(response){ + get('../php/get_tests.php?format=JSON').then(function (response) { document.getElementById("test-saved").innerHTML = null; var table = document.createElement("table"); table.innerHTML = "<tr><td>Test Filename</td><td>Count</td><td>Include</td></tr>"; @@ -710,50 +741,52 @@ var obj = { root: document.createElement("input"), parent: self.testSaves, - handleEvent: function(event) { + handleEvent: function (event) { this.parent.selectedURL = event.currentTarget.getAttribute("source"); var self = this; - get(this.parent.selectedURL).then(function(response){ + get(this.parent.selectedURL).then(function (response) { var parse = new DOMParser(); - testData.specification.decode(parse.parseFromString(response,'text/xml')); + testData.specification.decode(parse.parseFromString(response, 'text/xml')); self.parent.parent.generateFilters(testData.specification); self.parent.parent.getFileCount(); return true; - },function(error){ - console.log("ERROR: Could not get"+url); + }, function (error) { + console.log("ERROR: Could not get" + url); return false; }); } } obj.root.type = "radio"; obj.root.name = "test-include"; - obj.root.setAttribute("source",test.testName); - obj.root.addEventListener("change",obj); + obj.root.setAttribute("source", test.testName); + obj.root.addEventListener("change", obj); tableRowInclude.appendChild(obj.root); tableRow.appendChild(tableRowInclude); table.appendChild(tableRow); self.testSaves.inputs.push(obj); } document.getElementById("test-saved").appendChild(table); - },function(error){console.error(error);}); + }, function (error) { + console.error(error); + }); } - + this.filterDOM = document.createElement("div"); this.filterDOM.innerHTML = "<p>PreTest Filters</p><div id='filter-count'></div>"; this.filterObjects = []; - this.generateFilters = function(specification) { + this.generateFilters = function (specification) { // Filters are based on the pre and post global surverys - var FilterObject = function(parent,specification) { + var FilterObject = function (parent, specification) { this.parent = parent; this.specification = specification; this.rootDOM = document.createElement("div"); - this.rootDOM.innerHTML = "<span>ID: "+specification.id+", Type: "+specification.type+"</span>"; + this.rootDOM.innerHTML = "<span>ID: " + specification.id + ", Type: " + specification.type + "</span>"; this.rootDOM.className = "filter-entry"; - this.handleEvent = function(event) { - switch(this.specification.type) { + this.handleEvent = function (event) { + switch (this.specification.type) { case "number": var name = event.currentTarget.name; - eval("this."+name+" = event.currentTarget.value"); + eval("this." + name + " = event.currentTarget.value"); break; case "checkbox": break; @@ -762,29 +795,29 @@ } this.parent.getFileCount(); } - this.getFilterPairs = function() { + this.getFilterPairs = function () { var pairs = []; - switch(this.specification.type) { + switch (this.specification.type) { case "number": if (this.min != "") { - pairs.push([specification.id+"-min",this.min]); + pairs.push([specification.id + "-min", this.min]); } if (this.max != "") { - pairs.push([specification.id+"-max",this.max]); + pairs.push([specification.id + "-max", this.max]); } break; case "radio": case "checkbox": - for (var i=0; i<this.options.length; i++) { + for (var i = 0; i < this.options.length; i++) { if (!this.options[i].checked) { - pairs.push([specification.id+"-exclude-"+i,specification.options[i].name]); + pairs.push([specification.id + "-exclude-" + i, specification.options[i].name]); } } break; } return pairs; } - switch(specification.type) { + switch (specification.type) { case "number": // Number can be ranged by min/max levels this.min = ""; @@ -792,18 +825,18 @@ this.minDOM = document.createElement("input"); this.minDOM.type = "number"; this.minDOM.name = "min"; - this.minDOM.addEventListener("change",this); + this.minDOM.addEventListener("change", this); this.minDOMText = document.createElement("span"); this.minDOMText.textContent = "Minimum: "; var pairHolder = document.createElement("div"); pairHolder.appendChild(this.minDOMText); pairHolder.appendChild(this.minDOM); this.rootDOM.appendChild(pairHolder); - + this.maxDOM = document.createElement("input"); this.maxDOM.type = "number"; this.maxDOM.name = "max"; - this.maxDOM.addEventListener("change",this); + this.maxDOM.addEventListener("change", this); this.maxDOMText = document.createElement("span"); this.maxDOMText.textContent = "Maximum: "; var pairHolder = document.createElement("div"); @@ -814,16 +847,16 @@ case "radio": case "checkbox": this.options = []; - for (var i=0; i<specification.options.length; i++) { + for (var i = 0; i < specification.options.length; i++) { var option = specification.options[i]; var pairHolder = document.createElement("div"); var text = document.createElement("span"); text.textContent = option.text; var check = document.createElement("input"); check.type = "checkbox"; - check.setAttribute("option-index",i); + check.setAttribute("option-index", i); check.checked = true; - check.addEventListener("click",this); + check.addEventListener("click", this); this.options.push(check); pairHolder.appendChild(text); pairHolder.appendChild(check); @@ -835,18 +868,18 @@ } } var options = []; - if(specification.preTest) { + if (specification.preTest) { options = options.concat(specification.preTest.options); } if (specification.postTest) { options = options.concat(specification.postTest.options); } for (var survey_entry of options) { - switch(survey_entry.type) { + switch (survey_entry.type) { case "number": case "radio": case "checkbox": - var node = new FilterObject(this,survey_entry); + var node = new FilterObject(this, survey_entry); this.filterObjects.push(node); this.filterDOM.appendChild(node.rootDOM); break; @@ -858,41 +891,41 @@ document.getElementById("test-saved").appendChild(this.getDataButton.button); document.getElementById("test-saved").appendChild(this.getRawScoreData.root); } - this.getFilterString = function() { + this.getFilterString = function () { var pairs = []; for (var obj of this.filterObjects) { pairs = pairs.concat(obj.getFilterPairs()); } - var req_str = "?url="+this.testSaves.selectedURL; + var req_str = "?url=" + this.testSaves.selectedURL; var index = 0; - while(pairs[index] != undefined) { + while (pairs[index] != undefined) { req_str += '&'; - req_str += pairs[index][0]+"="+pairs[index][1]; + req_str += pairs[index][0] + "=" + pairs[index][1]; index++; } return req_str; } - this.getFilteredUrlArray = function() { - var req_str = "../php/get_filtered_count.php"+this.getFilterString(); - return get(req_str).then(function(response){ + this.getFilteredUrlArray = function () { + var req_str = "../php/get_filtered_count.php" + this.getFilterString(); + return get(req_str).then(function (response) { var urls = JSON.parse(response); return urls.urls; - },function(error){ + }, function (error) { console.error(error); }); } - this.getFileCount = function() { + this.getFileCount = function () { // First we must get the filter pairs - this.getFilteredUrlArray().then(function(response){ - var str = "Filtered to "+response.length+" file"; + this.getFilteredUrlArray().then(function (response) { + var str = "Filtered to " + response.length + " file"; if (response.length != 1) { str += "s."; } else { str += "."; } document.getElementById("filter-count").textContent = str; - },function(error){}); + }, function (error) {}); } - + this.init(); -} \ No newline at end of file +}
--- a/analysis/index.html Mon Nov 14 12:11:38 2016 +0000 +++ b/analysis/index.html Mon Nov 14 14:17:03 2016 +0000 @@ -1,29 +1,32 @@ <html lang="en"> - <head> - <meta charset="utf-8" /> - <link rel='stylesheet' href="analysis.css" type="text/css"/> - <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> - <script type="text/javascript" src="analysis.js"></script> - <script type="text/javascript" src="../js/specification.js"></script> - </head> - <body> - <h1>Web Audio Evaluation Toolbox: Analysis</h1> - <div id="test-saved"></div> - <button onclick="chartContext.clear();">Clear Charts</button> - <div id="test-charts"> - <p>Charts per test</p> - <button onclick="chartContext.drawTestMean();">Means</button> - <button onclick="chartContext.drawTestBoxplot();">Boxplot</button> - </div> - <div id="page-charts"> - <p>Charts per test page</p> - <button onclick="chartContext.drawPageMean();">Means</button> - </div> - <div id="element-charts"> - <p>Charts per element</p> - <button onclick="chartContext.drawElementHistogram();">Histogram</button> - </div> - - <div id="test-pages"></div> - </body> -</html> \ No newline at end of file + +<head> + <meta charset="utf-8" /> + <link rel='stylesheet' href="analysis.css" type="text/css" /> + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> + <script type="text/javascript" src="analysis.js"></script> + <script type="text/javascript" src="../js/specification.js"></script> +</head> + +<body> + <h1>Web Audio Evaluation Toolbox: Analysis</h1> + <div id="test-saved"></div> + <button onclick="chartContext.clear();">Clear Charts</button> + <div id="test-charts"> + <p>Charts per test</p> + <button onclick="chartContext.drawTestMean();">Means</button> + <button onclick="chartContext.drawTestBoxplot();">Boxplot</button> + </div> + <div id="page-charts"> + <p>Charts per test page</p> + <button onclick="chartContext.drawPageMean();">Means</button> + </div> + <div id="element-charts"> + <p>Charts per element</p> + <button onclick="chartContext.drawElementHistogram();">Histogram</button> + </div> + + <div id="test-pages"></div> +</body> + +</html>
--- a/css/core.css Mon Nov 14 12:11:38 2016 +0000 +++ b/css/core.css Mon Nov 14 14:17:03 2016 +0000 @@ -3,60 +3,53 @@ */ div.title { - width: 100%; - height: 50px; - margin-bottom: 10px; - font-size: 2em; + width: 100%; + height: 50px; + margin-bottom: 10px; + font-size: 2em; } - div.indicator-box { - position: absolute; - left: 150px; - top: 10px; - width: 300px; - height: 60px; - padding: 20px; - border-radius: 10px; - background-color: rgb(100,200,200); + position: absolute; + left: 150px; + top: 10px; + width: 300px; + height: 60px; + padding: 20px; + border-radius: 10px; + background-color: rgb(100, 200, 200); } - div.comment-div { - border:1px solid #444444; - max-width: 600px; - min-width: 400px; - float: left; - margin: 5px 10px 5px 5px; - height: 90px; + border: 1px solid #444444; + max-width: 600px; + min-width: 400px; + float: left; + margin: 5px 10px 5px 5px; + height: 90px; border-radius: 10px; } - div.comment-div span { - margin-left: 15px; + margin-left: 15px; } - div.popupHolder { - width: 500px; - min-height: 250px; - max-height: 400px; - background-color: #fff; - border-radius: 10px; - box-shadow: 0px 0px 50px #000; - z-index: 10; - position: fixed; + width: 500px; + min-height: 250px; + max-height: 400px; + background-color: #fff; + border-radius: 10px; + box-shadow: 0px 0px 50px #000; + z-index: 10; + position: fixed; } - div#popupContent { margin-top: 20px; margin-bottom: 35px; overflow: auto; } - div#popupContent iframe { width: 100%; border: 0px none; height: 290px; } - div#popupTitleHolder { width: inherit; min-height: 25px; @@ -66,11 +59,9 @@ padding: 8px; text-align: center; } - #popupTitle { white-space: pre-line; } - div#popupResponse { width: inherit; min-height: 50px; @@ -78,20 +69,18 @@ overflow: auto; position: relative; } - button.popupButton { - /* Button for popup window + /* Button for popup window */ - width: 50px; - height: 25px; - position: absolute; - border-radius: 5px; - border: #444; - border-width: 1px; - border-style: solid; - background-color: #fff; + width: 50px; + height: 25px; + position: absolute; + border-radius: 5px; + border: #444; + border-width: 1px; + border-style: solid; + background-color: #fff; } - div.popup-option-checbox { /* Popup window checkbox */ padding: 5px; @@ -99,46 +88,38 @@ width: -moz-fit-content; width: -webkit-fit-content; } - -div.popup-option-checbox input{ +div.popup-option-checbox input { /* Popup window checkbox */ margin-right: 15px; } - table.popup-option-list { margin: auto; } - table.popup-option-list tr { padding: 5px; } - table.popup-option-list tr td { padding: 5px; } - button#popup-proceed { bottom: 10px; right: 10px; } - button#popup-previous { bottom: 10px; left: 10px; } - div.testHalt { - /* Specify any colouring during the test halt for pre/post questions */ - background-color: rgba(0,0,0,0.5); - /* Don't mess with this bit */ - z-index: 9; - width: 100%; - height: 100%; - position: fixed; - left: 0px; - top: 0px; + /* Specify any colouring during the test halt for pre/post questions */ + background-color: rgba(0, 0, 0, 0.5); + /* Don't mess with this bit */ + z-index: 9; + width: 100%; + height: 100%; + position: fixed; + left: 0px; + top: 0px; } - div#lightbox-root { visibility: hidden; z-index: 20; @@ -146,80 +127,69 @@ min-height: 50px; max-height: 250px; } - div.lightbox-error { margin: 25px; margin-bottom: 50px; padding: 5px; border-radius: 5px; - background-color: rgb(255,220,220); - border: 2px rgb(200,0,0) solid; + background-color: rgb(255, 220, 220); + border: 2px rgb(200, 0, 0) solid; } - div.lightbox-warning { margin: 25px; margin-bottom: 50px; padding: 5px; border-radius: 5px; - background-color: rgb(255,255,220); - border: 2px rgb(255,250,0) solid; + background-color: rgb(255, 255, 220); + border: 2px rgb(255, 250, 0) solid; } - div.lightbox-message { margin: 25px; margin-bottom: 50px; padding: 5px; border-radius: 5px; - background-color: rgb(200,220,255); - border: 2px rgb(50,100,250) solid; + background-color: rgb(200, 220, 255); + border: 2px rgb(50, 100, 250) solid; } - div#lightbox-blanker { visibility: hidden; z-index: 19; } - button.outside-reference { - width:120px; - height:20px; - margin-bottom:5px; - position: absolute; + width: 120px; + height: 20px; + margin-bottom: 5px; + position: absolute; } - textarea.trackComment { - max-width: 594px; - min-width: 350px; - max-height: 60px; + max-width: 594px; + min-width: 350px; + max-height: 60px; resize: none; } - div.playhead { - width: 500px; - height: 50px; - background-color: #eee; - border-radius: 10px; - padding: 10px; + width: 500px; + height: 50px; + background-color: #eee; + border-radius: 10px; + padding: 10px; } - div.playhead-scrub-track { - width: 100%; - height: 10px; - border-style: solid; - border-width: 1px; + width: 100%; + height: 10px; + border-style: solid; + border-width: 1px; } - div#playhead-scrubber { - width: 10px; - height: 10px; - position: relative; - background-color: #000; + width: 10px; + height: 10px; + position: relative; + background-color: #000; } - div.master-volume-holder-inline { width: 100%; padding: 5px; } - div.master-volume-holder-float { position: absolute; top: 20px; @@ -227,15 +197,13 @@ width: 250px%; padding: 5px; } - div#master-volume-root { - margin:auto; + margin: auto; border: black 1px solid; border-radius: 5px; width: 250px; height: 40px; } - input#master-volume-control { width: 200px; height: 25px; @@ -243,14 +211,12 @@ margin: 0px; padding: 0px; } - span#master-volume-feedback { width: 45px; height: 25px; margin-left: 5px; float: left; } - div.error-colour { background-color: #FF8F8F; } @@ -258,13 +224,11 @@ background-color: #FF8F8F; color: black; } - div.calibration-holder { text-align: center; align-content: center; height: auto; } - div.calibration-slider { width: 50px; margin: 2px; @@ -272,11 +236,11 @@ align-content: center; float: left; } - -div.calibration-slider input[type=range][orient=vertical] -{ - writing-mode: bt-lr; /* IE */ - -webkit-appearance: slider-vertical; /* WebKit */ +div.calibration-slider input[type=range][orient=vertical] { + writing-mode: bt-lr; + /* IE */ + -webkit-appearance: slider-vertical; + /* WebKit */ width: 8px; padding: 0 5px; height: 290px;
--- a/index.html Mon Nov 14 12:11:38 2016 +0000 +++ b/index.html Mon Nov 14 14:17:03 2016 +0000 @@ -1,55 +1,57 @@ <!DOCTYPE html> <html lang="en"> - <head> - <meta http-equiv="content-type" content="text/html; charset=utf-8"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> - <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame + + <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame Remove this if you use the .htaccess --> - <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> - <title>Web Audio Evaluation Tool</title> - <meta name="description" content="" /> - <meta name="author" content="" /> - - <!-- Load up the default core JS and CSS files--> - <link rel='stylesheet' type='text/css' href='css/core.css'> - <!-- Use jQuery hosted from Google CDN --> - <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>--> - <script type="text/javascript" src="js/jquery-2.1.4.js"></script> - <script type="text/javascript" src="js/loader.js"></script> - </head> + <title>Web Audio Evaluation Tool</title> + <meta name="description" content="" /> + <meta name="author" content="" /> - <body> - <div id='topLevelBody'> - <h1>Web Audio Evaluation Tool</h1> - <h2>Start menu </h2> - <ul> - <li><a href="test.html?url=tests/examples/project.xml" target="_blank">APE interface test example</a></li> - <li><a href="test.html?url=tests/examples/mushra_example.xml" target="_blank">MUSHRA interface test example</a></li> - <li><a href="test.html?url=tests/examples/AB_example.xml" target="_blank">AB interface test example</a></li> - <li><a href="test.html?url=tests/examples/horizontal_example.xml" target="_blank">Horizontal interface test example</a></li> - <li><a href="test.html?url=tests/examples/radio_example.xml" target="_blank">Radio interface test example</a></li> - <li><a href="test_create.html" target="_blank">Test creator</a></li> - <li><a href="analyse.html" target="_blank">Analysis and diagnostics of results</a></li> - </ul> - <br> - <ul> - <li><a href="LICENSE.txt" target="_blank">License</a></li> - <li><a href="CITING.txt" target="_blank">Citing</a></li> - <li><a href="docs/Instructions/Instructions.pdf" target="_blank">Instructions</a></li> - </ul> - </div> - <div id="popupHolder" class="popupHolder" style="visibility: hidden"> - <div id="popupContent"> - <div id="popupTitleHolder"> - <span id="popupTitle"></span> - </div> - <div id="popupResponse"></div> + <!-- Load up the default core JS and CSS files--> + <link rel='stylesheet' type='text/css' href='css/core.css'> + <!-- Use jQuery hosted from Google CDN --> + <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>--> + <script type="text/javascript" src="js/jquery-2.1.4.js"></script> + <script type="text/javascript" src="js/loader.js"></script> +</head> + +<body> + <div id='topLevelBody'> + <h1>Web Audio Evaluation Tool</h1> + <h2>Start menu </h2> + <ul> + <li><a href="test.html?url=tests/examples/project.xml" target="_blank">APE interface test example</a></li> + <li><a href="test.html?url=tests/examples/mushra_example.xml" target="_blank">MUSHRA interface test example</a></li> + <li><a href="test.html?url=tests/examples/AB_example.xml" target="_blank">AB interface test example</a></li> + <li><a href="test.html?url=tests/examples/horizontal_example.xml" target="_blank">Horizontal interface test example</a></li> + <li><a href="test.html?url=tests/examples/radio_example.xml" target="_blank">Radio interface test example</a></li> + <li><a href="test_create.html" target="_blank">Test creator</a></li> + <li><a href="analyse.html" target="_blank">Analysis and diagnostics of results</a></li> + </ul> + <br> + <ul> + <li><a href="LICENSE.txt" target="_blank">License</a></li> + <li><a href="CITING.txt" target="_blank">Citing</a></li> + <li><a href="docs/Instructions/Instructions.pdf" target="_blank">Instructions</a></li> + </ul> + </div> + <div id="popupHolder" class="popupHolder" style="visibility: hidden"> + <div id="popupContent"> + <div id="popupTitleHolder"> + <span id="popupTitle"></span> </div> - <button id="popup-proceed" class="popupButton">Next</button> - <button id="popup-previous" class="popupButton">Back</button> + <div id="popupResponse"></div> </div> - <div class="testHalt" style="visibility: hidden"></div> - </body> + <button id="popup-proceed" class="popupButton">Next</button> + <button id="popup-previous" class="popupButton">Back</button> + </div> + <div class="testHalt" style="visibility: hidden"></div> +</body> + </html>
--- a/interfaces/AB.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/AB.css Mon Nov 14 14:17:03 2016 +0000 @@ -1,95 +1,79 @@ body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #fff + /* Set the background colour (note US English spelling) to grey*/ + background-color: #fff } - div.pageTitle { - width: auto; - height: 20px; - margin: 10px 0px; + width: auto; + height: 20px; + margin: 10px 0px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - button.big-button { - width: 250px; - height: 40px; - font-size: 1.2em; + width: 250px; + height: 40px; + font-size: 1.2em; } - div.interface-buttons { height: 40px; } - div#outside-reference-holder { display: flex; align-content: center; justify-content: center; margin-bottom: 5px; } - button.outside-reference { height: 40px; position: inherit; margin: 0px 5px; } - div.comparator-holder { - width: 260px; - height: 300px; - border: black 1px solid; + width: 260px; + height: 300px; + border: black 1px solid; float: left; - padding-top: 5px; + padding-top: 5px; margin: 25px; } - div.comparator-selector { - width: 248px; - height: 250px; - border: black 1px solid; - position: relative; - background-color: #FF0000; + width: 248px; + height: 250px; + border: black 1px solid; + position: relative; + background-color: #FF0000; border-radius: 20px; } - div.disabled { - background-color: #AAA; + background-color: #AAA; } - div.selected { - background-color: #008000; + background-color: #008000; } - div.comparator-selector span { - font-size: 4em; + font-size: 4em; } - button.comparator-button { - width: 250px; - height: 38px; - position: relative; - margin-top: 5px; + width: 250px; + height: 38px; + position: relative; + margin-top: 5px; } - div.playhead { margin: 5px; } - div#page-count { float: left; margin: 0px 5px; } - div#master-volume-holder { position: absolute; top: 10px; left: 120px; -} \ No newline at end of file +}
--- a/interfaces/AB.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/AB.js Mon Nov 14 14:17:03 2016 +0000 @@ -2,15 +2,15 @@ loadInterface(); function loadInterface() { - // Get the dimensions of the screen available to the page - var width = window.innerWidth; - var height = window.innerHeight; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Custom comparator Object - Interface.prototype.comparator = null; - - Interface.prototype.checkScaleRange = function(min, max) { + // Get the dimensions of the screen available to the page + var width = window.innerWidth; + var height = window.innerHeight; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Custom comparator Object + Interface.prototype.comparator = null; + + Interface.prototype.checkScaleRange = function (min, max) { var page = testState.getCurrentTestPage(); var audioObjects = audioEngineContext.audioObjects; var state = true; @@ -19,166 +19,170 @@ var maxRanking = -Infinity; for (var ao of audioObjects) { var rank = ao.interfaceDOM.getValue(); - if (rank < minRanking) {minRanking = rank;} - if (rank > maxRanking) {maxRanking = rank;} + if (rank < minRanking) { + minRanking = rank; + } + if (rank > maxRanking) { + maxRanking = rank; + } } - if (maxRanking*100 < max) { + if (maxRanking * 100 < max) { str += "At least one fragment must be selected." state = false; } if (!state) { console.log(str); this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); + interfaceContext.lightbox.post("Message", str); } return state; } - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // 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'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // 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'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - + } + }; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - // Construct the AB Boxes - var boxes = document.createElement('div'); - boxes.align = "center"; - boxes.id = "box-holders"; + + // Construct the AB Boxes + var boxes = document.createElement('div'); + boxes.align = "center"; + boxes.id = "box-holders"; boxes.style.float = "left"; - - var submit = document.createElement('button'); - submit.id = "submit"; - submit.onclick = buttonSubmitClick; - submit.className = "big-button"; - submit.textContent = "submit"; - submit.style.position = "relative"; - submit.style.left = (window.innerWidth-250)/2 + 'px'; - - feedbackHolder.appendChild(boxes); - + + var submit = document.createElement('button'); + submit.id = "submit"; + submit.onclick = buttonSubmitClick; + submit.className = "big-button"; + submit.textContent = "submit"; + submit.style.position = "relative"; + submit.style.left = (window.innerWidth - 250) / 2 + 'px'; + + feedbackHolder.appendChild(boxes); + // Create holder for comment boxes var comments = document.createElement("div"); comments.id = "comment-box-holder"; - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); testContent.appendChild(outsideRef); - testContent.appendChild(feedbackHolder); - testContent.appendChild(submit); + testContent.appendChild(feedbackHolder); + testContent.appendChild(submit); testContent.appendChild(comments); - interfaceContext.insertPoint.appendChild(testContent); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); } -function loadTest(audioHolderObject) -{ - var feedbackHolder = document.getElementById('feedbackHolder'); - var interfaceObj = audioHolderObject.interfaces; - if (interfaceObj.length > 1) - { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - +function loadTest(audioHolderObject) { + var feedbackHolder = document.getElementById('feedbackHolder'); + var interfaceObj = audioHolderObject.interfaces; + if (interfaceObj.length > 1) { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + var commentHolder = document.getElementById('comment-box-holder'); commentHolder.innerHTML = ""; - + // Delete outside reference - var outsideReferenceHolder = document.getElementById("outside-reference-holder"); + var outsideReferenceHolder = document.getElementById("outside-reference-holder"); outsideReferenceHolder.innerHTML = ""; - + // Set the page title if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { document.getElementById("test-title").textContent = audioHolderObject.title } - - if(interfaceObj.title != null) - { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - + + if (interfaceObj.title != null) { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); // Clear the interfaceElements { var node = document.getElementById('playback-holder'); - if (node){feedbackHolder.removeChild(node);} + if (node) { + feedbackHolder.removeChild(node); + } node = document.getElementById('page-count'); - if (node){document.getElementById('interface-buttons').removeChild(node);} + if (node) { + document.getElementById('interface-buttons').removeChild(node); + } node = document.getElementById('master-volume-holder-float'); - if (node){feedbackHolder.removeChild(node);} + if (node) { + feedbackHolder.removeChild(node); + } } - + // Populate the comparator object - interfaceContext.comparator = new comparator(audioHolderObject); - - for (var option of interfaceOptions) - { - if (option.type == "show") - { - switch(option.name) { + interfaceContext.comparator = new comparator(audioHolderObject); + + for (var option of interfaceOptions) { + if (option.type == "show") { + switch (option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.id = 'playback-holder'; playbackHolder.style.width = "100%"; @@ -190,201 +194,178 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; document.getElementById('interface-buttons').appendChild(pagecountHolder); } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; break; case "volume": - if (document.getElementById('master-volume-holder-float') == null) - { + if (document.getElementById('master-volume-holder-float') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": // Generate one comment box per presented page - for (var element of audioEngineContext.audioObjects) - { + for (var element of audioEngineContext.audioObjects) { interfaceContext.commentBoxes.createCommentBox(element); } - interfaceContext.commentBoxes.showCommentBoxes(commentHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(commentHolder, true); break; } } } - - $(audioHolderObject.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - commentHolder.appendChild(node.holder); - }); - - resizeWindow(null); + + $(audioHolderObject.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + commentHolder.appendChild(node.holder); + }); + + resizeWindow(null); } -function comparator(audioHolderObject) -{ - this.comparatorBox = function(audioElement,id,text) - { - this.parent = audioElement; - this.id = id; - this.value = 0; - this.disabled = true; - this.box = document.createElement('div'); - this.box.className = 'comparator-holder'; - this.box.setAttribute('track-id',audioElement.id); - this.box.id = 'comparator-'+text; - this.selector = document.createElement('div'); - this.selector.className = 'comparator-selector disabled'; - var selectorText = document.createElement('span'); - selectorText.textContent = text; - this.selector.appendChild(selectorText); - this.playback = document.createElement('button'); - this.playback.className = 'comparator-button'; - this.playback.disabled = true; - this.playback.textContent = "Listen"; - this.box.appendChild(this.selector); - this.box.appendChild(this.playback); - this.selector.onclick = function(event) - { - var time = audioEngineContext.timer.getTestTime(); - if ($(event.currentTarget).hasClass('disabled')) - { - console.log("Please wait until sample has loaded"); - return; - } - if (audioEngineContext.status == 0) - { - interfaceContext.lightbox.post("Message","Please listen to the samples before making a selection"); - console.log("Please listen to the samples before making a selection"); - return; +function comparator(audioHolderObject) { + this.comparatorBox = function (audioElement, id, text) { + this.parent = audioElement; + this.id = id; + this.value = 0; + this.disabled = true; + this.box = document.createElement('div'); + this.box.className = 'comparator-holder'; + this.box.setAttribute('track-id', audioElement.id); + this.box.id = 'comparator-' + text; + this.selector = document.createElement('div'); + this.selector.className = 'comparator-selector disabled'; + var selectorText = document.createElement('span'); + selectorText.textContent = text; + this.selector.appendChild(selectorText); + this.playback = document.createElement('button'); + this.playback.className = 'comparator-button'; + this.playback.disabled = true; + this.playback.textContent = "Listen"; + this.box.appendChild(this.selector); + this.box.appendChild(this.playback); + this.selector.onclick = function (event) { + var time = audioEngineContext.timer.getTestTime(); + if ($(event.currentTarget).hasClass('disabled')) { + console.log("Please wait until sample has loaded"); + return; } - var id = event.currentTarget.parentElement.getAttribute('track-id'); - interfaceContext.comparator.selected = id; + if (audioEngineContext.status == 0) { + interfaceContext.lightbox.post("Message", "Please listen to the samples before making a selection"); + console.log("Please listen to the samples before making a selection"); + return; + } + var id = event.currentTarget.parentElement.getAttribute('track-id'); + interfaceContext.comparator.selected = id; if ($(event.currentTarget).hasClass("selected")) { $(".comparator-selector").removeClass('selected'); - for (var i=0; i<interfaceContext.comparator.comparators.length; i++) - { + for (var i = 0; i < interfaceContext.comparator.comparators.length; i++) { var obj = interfaceContext.comparator.comparators[i]; - obj.parent.metric.moved(time,0); + obj.parent.metric.moved(time, 0); obj.value = 0; } } else { $(".comparator-selector").removeClass('selected'); $(event.currentTarget).addClass('selected'); - for (var i=0; i<interfaceContext.comparator.comparators.length; i++) - { + for (var i = 0; i < interfaceContext.comparator.comparators.length; i++) { var obj = interfaceContext.comparator.comparators[i]; if (i == id) { obj.value = 1; } else { obj.value = 0; } - obj.parent.metric.moved(time,obj.value); + obj.parent.metric.moved(time, obj.value); } - console.log("Selected "+id+' ('+time+')'); + console.log("Selected " + id + ' (' + time + ')'); } - }; - this.playback.setAttribute("playstate","ready"); - this.playback.onclick = function(event) - { - var id = event.currentTarget.parentElement.getAttribute('track-id'); - if (event.currentTarget.getAttribute("playstate") == "ready") - { + }; + this.playback.setAttribute("playstate", "ready"); + this.playback.onclick = function (event) { + var id = event.currentTarget.parentElement.getAttribute('track-id'); + if (event.currentTarget.getAttribute("playstate") == "ready") { audioEngineContext.play(id); } else if (event.currentTarget.getAttribute("playstate") == "playing") { audioEngineContext.stop(); } - - }; - - this.enable = function() - { - if (this.parent.state == 1) - { - $(this.selector).removeClass('disabled'); - this.playback.disabled = false; - } - }; - this.updateLoading = function(progress) - { - if (progress != 100) - { - progress = String(progress); - progress = progress.split('.')[0]; - this.playback.textContent = progress+'%'; - } else { - this.playback.textContent = "Play"; - } - }; - this.error = function() { + + }; + + this.enable = function () { + if (this.parent.state == 1) { + $(this.selector).removeClass('disabled'); + this.playback.disabled = false; + } + }; + this.updateLoading = function (progress) { + if (progress != 100) { + progress = String(progress); + progress = progress.split('.')[0]; + this.playback.textContent = progress + '%'; + } else { + this.playback.textContent = "Play"; + } + }; + this.error = function () { // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } - this.startPlayback = function() - { + this.startPlayback = function () { if (this.parent.specification.parent.playOne || specification.playOne) { $('.comparator-button').text('Wait'); - $('.comparator-button').attr("disabled","true"); + $('.comparator-button').attr("disabled", "true"); $(this.playback).removeAttr("disabled"); } else { $('.comparator-button').text('Listen'); } $(this.playback).text('Stop'); - this.playback.setAttribute("playstate","playing"); + this.playback.setAttribute("playstate", "playing"); }; - this.stopPlayback = function() - { + this.stopPlayback = function () { if (this.playback.getAttribute("playstate") == "playing") { $('.comparator-button').text('Listen'); $('.comparator-button').removeAttr("disabled"); - this.playback.setAttribute("playstate","ready"); + this.playback.setAttribute("playstate", "ready"); } }; - this.exportXMLDOM = function(audioObject) - { - var node = storage.document.createElement('value'); - node.textContent = this.value; - return node; - }; - this.getValue = function() { - return this.value; - }; - this.getPresentedId = function() - { - return this.selector.children[0].textContent; - }; - this.canMove = function() - { - return false; - }; - }; - - this.boxHolders = document.getElementById('box-holders'); - this.boxHolders.innerHTML = ""; - this.comparators = []; - this.selected = null; - - // First generate the Audio Objects for the Audio Engine - for (var index=0; index<audioHolderObject.audioElements.length; index++) - { - var element = audioHolderObject.audioElements[index]; + this.exportXMLDOM = function (audioObject) { + var node = storage.document.createElement('value'); + node.textContent = this.value; + return node; + }; + this.getValue = function () { + return this.value; + }; + this.getPresentedId = function () { + return this.selector.children[0].textContent; + }; + this.canMove = function () { + return false; + }; + }; + + this.boxHolders = document.getElementById('box-holders'); + this.boxHolders.innerHTML = ""; + this.comparators = []; + this.selected = null; + + // First generate the Audio Objects for the Audio Engine + for (var index = 0; index < audioHolderObject.audioElements.length; index++) { + var element = audioHolderObject.audioElements[index]; var audioObject = audioEngineContext.newTrack(element); - if (index == audioHolderObject.outsideReference || element.type == 'outside-reference') - { - var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); - audioObject.bindInterface(orNode); + if (index == audioHolderObject.outsideReference || element.type == 'outside-reference') { + var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); + audioObject.bindInterface(orNode); } else { var label; - switch(audioObject.specification.parent.label) { + switch (audioObject.specification.parent.label) { case "none": label = ""; break; case "number": - label = ""+index; + label = "" + index; break; case "letter": label = String.fromCharCode(97 + index); @@ -393,106 +374,109 @@ label = String.fromCharCode(65 + index); break; } - var node = new this.comparatorBox(audioObject,index,label); + var node = new this.comparatorBox(audioObject, index, label); audioObject.bindInterface(node); this.comparators.push(node); this.boxHolders.appendChild(node.box); } - } - return this; + } + return this; } -function resizeWindow(event) -{ - document.getElementById('submit').style.left = (window.innerWidth-250)/2 + 'px'; - var numObj = interfaceContext.comparator.comparators.length; - var boxW = numObj*312; +function resizeWindow(event) { + document.getElementById('submit').style.left = (window.innerWidth - 250) / 2 + 'px'; + var numObj = interfaceContext.comparator.comparators.length; + var boxW = numObj * 312; var diff = window.innerWidth - boxW; - while (diff < 0) - { - numObj = Math.ceil(numObj/2); - boxW = numObj*312; + while (diff < 0) { + numObj = Math.ceil(numObj / 2); + boxW = numObj * 312; diff = window.innerWidth - boxW; } - document.getElementById('box-holders').style.marginLeft = diff/2 + 'px'; - document.getElementById('box-holders').style.marginRight = diff/2 + 'px'; + document.getElementById('box-holders').style.marginLeft = diff / 2 + 'px'; + document.getElementById('box-holders').style.marginRight = diff / 2 + 'px'; document.getElementById('box-holders').style.width = boxW + 'px'; - + var outsideRef = document.getElementById('outside-reference'); - if(outsideRef != null) - { - outsideRef.style.left = (window.innerWidth-120)/2 + 'px'; - } + if (outsideRef != null) { + outsideRef.style.left = (window.innerWidth - 120) / 2 + 'px'; + } } -function buttonSubmitClick() -{ - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkFragmentsFullyPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); - break; - } +function buttonSubmitClick() { + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - if (canContinue) - { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Warning",'You have not started the test! Please click play on a sample to begin the test!'); - return; - } - } - testState.advanceState(); - } + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkFragmentsFullyPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Warning", 'You have not started the test! Please click play on a sample to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +}
--- a/interfaces/ABX.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/ABX.css Mon Nov 14 14:17:03 2016 +0000 @@ -1,80 +1,66 @@ body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #fff + /* Set the background colour (note US English spelling) to grey*/ + background-color: #fff } - div.pageTitle { - width: auto; - height: 20px; - margin-top: 20px; + width: auto; + height: 20px; + margin-top: 20px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - button.big-button { - width: 250px; - height: 40px; - font-size: 1.2em; + width: 250px; + height: 40px; + font-size: 1.2em; } - div.comparator-holder { - width: 260px; - height: 300px; - border: black 1px solid; + width: 260px; + height: 300px; + border: black 1px solid; float: left; - padding-top: 5px; + padding-top: 5px; margin: 25px; } - div.comparator-selector { - width: 248px; - height: 250px; - border: black 1px solid; - position: relative; - background-color: #FF0000; + width: 248px; + height: 250px; + border: black 1px solid; + position: relative; + background-color: #FF0000; border-radius: 20px; } - div.disabled { - background-color: #AAA; + background-color: #AAA; } - div.selected { - background-color: #008000; + background-color: #008000; } - -div.comparator-selector.inactive{ - background-color: yellow !important; +div.comparator-selector.inactive { + background-color: yellow !important; } - div.comparator-selector span { - font-size: 4em; + font-size: 4em; } - button.comparator-button { - width: 250px; - height: 38px; - position: relative; - margin-top: 5px; + width: 250px; + height: 38px; + position: relative; + margin-top: 5px; } - div.playhead { margin: 5px; } - div#page-count { float: left; margin: 0px 5px; } - div#master-volume-holder { position: absolute; top: 10px;
--- a/interfaces/ABX.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/ABX.js Mon Nov 14 14:17:03 2016 +0000 @@ -7,12 +7,12 @@ loadInterface(); function loadInterface() { - // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, - // holding div's, or setting up any nodes which are present for the entire test sequence - + // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, + // holding div's, or setting up any nodes which are present for the entire test sequence + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - Interface.prototype.checkScaleRange = function(min, max) { + + Interface.prototype.checkScaleRange = function (min, max) { var page = testState.getCurrentTestPage(); var audioObjects = audioEngineContext.audioObjects; var state = true; @@ -21,151 +21,149 @@ var maxRanking = -Infinity; for (var ao of audioObjects) { var rank = ao.interfaceDOM.getValue(); - if (rank < minRanking) {minRanking = rank;} - if (rank > maxRanking) {maxRanking = rank;} + if (rank < minRanking) { + minRanking = rank; + } + if (rank > maxRanking) { + maxRanking = rank; + } } - if (maxRanking*100 < max) { + if (maxRanking * 100 < max) { str += "At least one fragment must be selected." state = false; } if (!state) { console.log(str); this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); + interfaceContext.lightbox.post("Message", str); } return state; } - + // Custom comparator Object - Interface.prototype.comparator = null; - + Interface.prototype.comparator = null; + // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - + // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // Insert the titleSpan element into the title div element. - title.appendChild(titleSpan); - + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // 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'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + 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'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - - // Construct the AB Boxes - var boxes = document.createElement('div'); - boxes.align = "center"; - boxes.id = "box-holders"; + } + }; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + + // Construct the AB Boxes + var boxes = document.createElement('div'); + boxes.align = "center"; + boxes.id = "box-holders"; boxes.style.float = "left"; - - var submit = document.createElement('button'); - submit.id = "submit"; - submit.onclick = buttonSubmitClick; - submit.className = "big-button"; - submit.textContent = "submit"; - submit.style.position = "relative"; - submit.style.left = (window.innerWidth-250)/2 + 'px'; - - feedbackHolder.appendChild(boxes); - + + var submit = document.createElement('button'); + submit.id = "submit"; + submit.onclick = buttonSubmitClick; + submit.className = "big-button"; + submit.textContent = "submit"; + submit.style.position = "relative"; + submit.style.left = (window.innerWidth - 250) / 2 + 'px'; + + feedbackHolder.appendChild(boxes); + // Create holder for comment boxes var comments = document.createElement("div"); comments.id = "comment-box-holder"; - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); - testContent.appendChild(feedbackHolder); - testContent.appendChild(submit); + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); + testContent.appendChild(feedbackHolder); + testContent.appendChild(submit); testContent.appendChild(comments); - interfaceContext.insertPoint.appendChild(testContent); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); }; -function loadTest(page) -{ - // Called each time a new test page is to be build. The page specification node is the only item passed in +function loadTest(page) { + // Called each time a new test page is to be build. The page specification node is the only item passed in document.getElementById('box-holders').innerHTML = ""; - + var interfaceObj = page.interfaces; - if (interfaceObj.length > 1) - { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - + if (interfaceObj.length > 1) { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + var commentHolder = document.getElementById("comment-box-holder"); commentHolder.innerHTML = ""; - + // Set the page title if (typeof page.title == "string" && page.title.length > 0) { document.getElementById("test-title").textContent = page.title } - - if(interfaceObj.title != null) - { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - + + if (interfaceObj.title != null) { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + interfaceContext.comparator = new comparator(page); - + var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); - for (var option of interfaceOptions) - { - if (option.type == "show") - { - switch(option.name) { + for (var option of interfaceOptions) { + if (option.type == "show") { + switch (option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.style.width = "100%"; playbackHolder.style.float = "left"; @@ -176,46 +174,41 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); break; case "volume": - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": // Generate one comment box per presented page - for (var element of audioEngineContext.audioObjects) - { + for (var element of audioEngineContext.audioObjects) { interfaceContext.commentBoxes.createCommentBox(element); } - interfaceContext.commentBoxes.showCommentBoxes(commentHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(commentHolder, true); break; } } } - - $(page.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - commentHolder.appendChild(node.holder); - }); - + + $(page.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + commentHolder.appendChild(node.holder); + }); + resizeWindow(null); } -function comparator(page) -{ +function comparator(page) { // Build prototype constructor - this.interfaceObject = function(element,label) - { + this.interfaceObject = function (element, label) { // An example node, you can make this however you want for each audioElement. // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following // You attach them by calling audioObject.bindInterface( ) @@ -225,173 +218,158 @@ this.disabled = true; this.box = document.createElement('div'); this.box.className = 'comparator-holder'; - this.box.setAttribute('track-id',element.id); - this.box.id = 'comparator-'+label; + this.box.setAttribute('track-id', element.id); + this.box.id = 'comparator-' + label; this.selector = document.createElement('div'); - this.selector.className = 'comparator-selector disabled'; - var selectorText = document.createElement('span'); - selectorText.textContent = label; - this.selector.appendChild(selectorText); - this.playback = document.createElement('button'); - this.playback.className = 'comparator-button'; - this.playback.disabled = true; - this.playback.textContent = "Listen"; - this.box.appendChild(this.selector); - this.box.appendChild(this.playback); - this.selector.onclick = function(event) - { + this.selector.className = 'comparator-selector disabled'; + var selectorText = document.createElement('span'); + selectorText.textContent = label; + this.selector.appendChild(selectorText); + this.playback = document.createElement('button'); + this.playback.className = 'comparator-button'; + this.playback.disabled = true; + this.playback.textContent = "Listen"; + this.box.appendChild(this.selector); + this.box.appendChild(this.playback); + this.selector.onclick = function (event) { var label = event.currentTarget.children[0].textContent; - if (label == "X" || label == "x") {return;} - var time = audioEngineContext.timer.getTestTime(); - if ($(event.currentTarget).hasClass('disabled')) - { - console.log("Please wait until sample has loaded"); - return; - } - if (audioEngineContext.status == 0) - { - interfaceContext.lightbox.post("Message", "Please listen to the samples before making a selection"); - console.log("Please listen to the samples before making a selection"); - return; + if (label == "X" || label == "x") { + return; } - var id = event.currentTarget.parentElement.getAttribute('track-id'); - interfaceContext.comparator.selected = id; + var time = audioEngineContext.timer.getTestTime(); + if ($(event.currentTarget).hasClass('disabled')) { + console.log("Please wait until sample has loaded"); + return; + } + if (audioEngineContext.status == 0) { + interfaceContext.lightbox.post("Message", "Please listen to the samples before making a selection"); + console.log("Please listen to the samples before making a selection"); + return; + } + var id = event.currentTarget.parentElement.getAttribute('track-id'); + interfaceContext.comparator.selected = id; if ($(event.currentTarget).hasClass("selected")) { $(".comparator-selector").removeClass('selected'); - for (var i=0; i<interfaceContext.comparator.pair.length; i++) - { + for (var i = 0; i < interfaceContext.comparator.pair.length; i++) { var obj = interfaceContext.comparator.pair[i]; - obj.parent.metric.moved(time,0); + obj.parent.metric.moved(time, 0); obj.value = 0; } } else { $(".comparator-selector").removeClass('selected'); $(event.currentTarget).addClass('selected'); - for (var i=0; i<interfaceContext.comparator.pair.length; i++) - { + for (var i = 0; i < interfaceContext.comparator.pair.length; i++) { var obj = interfaceContext.comparator.pair[i]; if (i == id) { obj.value = 1; } else { obj.value = 0; } - obj.parent.metric.moved(time,obj.value); + obj.parent.metric.moved(time, obj.value); } - console.log("Selected "+id+' ('+time+')'); + console.log("Selected " + id + ' (' + time + ')'); } - }; - this.playback.setAttribute("playstate","ready"); - this.playback.onclick = function(event) - { - var id = event.currentTarget.parentElement.getAttribute('track-id'); - if (event.currentTarget.getAttribute("playstate") == "ready") - { + }; + this.playback.setAttribute("playstate", "ready"); + this.playback.onclick = function (event) { + var id = event.currentTarget.parentElement.getAttribute('track-id'); + if (event.currentTarget.getAttribute("playstate") == "ready") { audioEngineContext.play(id); } else if (event.currentTarget.getAttribute("playstate") == "playing") { audioEngineContext.stop(); } - - }; - this.enable = function() - { + + }; + this.enable = function () { // This is used to tell the interface object that playback of this node is ready - if (this.parent.state == 1) - { - $(this.selector).removeClass('disabled'); - this.playback.disabled = false; - } + if (this.parent.state == 1) { + $(this.selector).removeClass('disabled'); + this.playback.disabled = false; + } }; - this.updateLoading = function(progress) - { + this.updateLoading = function (progress) { // progress is a value from 0 to 100 indicating the current download state of media files - if (progress != 100) - { - progress = String(progress); - progress = progress.split('.')[0]; - this.playback.textContent = progress+'%'; - } else { - this.playback.textContent = "Play"; - } + if (progress != 100) { + progress = String(progress); + progress = progress.split('.')[0]; + this.playback.textContent = progress + '%'; + } else { + this.playback.textContent = "Play"; + } }; - this.error = function() { + this.error = function () { // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); }; - this.startPlayback = function() - { + this.startPlayback = function () { if (this.parent.specification.parent.playOne || specification.playOne) { $('.comparator-button').text('Wait'); - $('.comparator-button').attr("disabled","true"); + $('.comparator-button').attr("disabled", "true"); $(this.playback).removeAttr("disabled"); } else { $('.comparator-button').text('Listen'); } $(this.playback).text('Stop'); - this.playback.setAttribute("playstate","playing"); + this.playback.setAttribute("playstate", "playing"); }; - this.stopPlayback = function() - { + this.stopPlayback = function () { if (this.playback.getAttribute("playstate") == "playing") { $('.comparator-button').text('Listen'); $('.comparator-button').removeAttr("disabled"); - this.playback.setAttribute("playstate","ready"); + this.playback.setAttribute("playstate", "ready"); } }; - this.getValue = function() - { + this.getValue = function () { // Return the current value of the object. If there is no value, return 0 return this.value; }; - this.getPresentedId = function() - { + this.getPresentedId = function () { // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale return this.selector.children[0].textContent; }; - this.canMove = function() - { + this.canMove = function () { // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. // These are checked primarily if the interface check option 'fragmentMoved' is enabled. return false; }; - this.exportXMLDOM = function(audioObject) { + this.exportXMLDOM = function (audioObject) { // Called by the audioObject holding this element to export the interface <value> node. // If there is no value node (such as outside reference), return null // 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 // Use storage.document.createElement('value'); to generate the XML node. var node = storage.document.createElement('value'); - node.textContent = this.value; - return node; + node.textContent = this.value; + return node; }; - this.error = function() { + this.error = function () { // If there is an error with the audioObject, this will be called to indicate a failure } }; // Ensure there are only two comparisons per page if (page.audioElements.length != 2) { - console.error('FATAL - There must be 2 <audioelement> nodes on each <page>: '+page.id); + console.error('FATAL - There must be 2 <audioelement> nodes on each <page>: ' + page.id); return; } // Build the three audio elements this.pair = []; this.X = null; this.boxHolders = document.getElementById('box-holders'); - for (var index=0; index<page.audioElements.length; index++) { + for (var index = 0; index < page.audioElements.length; index++) { var element = page.audioElements[index]; - if (element.type != 'normal') - { - console.log("WARNING - ABX can only have normal elements. Page "+page.id+", Element "+element.id); + if (element.type != 'normal') { + console.log("WARNING - ABX can only have normal elements. Page " + page.id + ", Element " + element.id); element.type = "normal"; - } + } var audioObject = audioEngineContext.newTrack(element); var label; - switch(audioObject.specification.parent.label) { + switch (audioObject.specification.parent.label) { case "none": label = ""; break; case "number": - label = ""+index; + label = "" + index; break; case "letter": label = String.fromCharCode(97 + index); @@ -400,7 +378,7 @@ label = String.fromCharCode(65 + index); break; } - var node = new this.interfaceObject(audioObject,label); + var node = new this.interfaceObject(audioObject, label); audioObject.bindInterface(node); this.pair.push(node); this.boxHolders.appendChild(node.box); @@ -408,25 +386,29 @@ var elementId = Math.floor(Math.random() * 2); //Randomly pick A or B to be X var element = new page.audioElementNode(specification); for (var atr in page.audioElements[elementId]) { - eval("element."+atr+" = page.audioElements[elementId]."+atr); + eval("element." + atr + " = page.audioElements[elementId]." + atr); } element.id += "-X"; - if (typeof element.name == "string") {element.name+="-X";} + if (typeof element.name == "string") { + element.name += "-X"; + } page.audioElements.push(element); // Create the save place-holder for the 'X' element var root = testState.currentStore.XMLDOM; var aeNode = storage.document.createElement('audioelement'); - aeNode.setAttribute('ref',element.id); - if (typeof element.name == "string"){aeNode.setAttribute('name',element.name);} - aeNode.setAttribute('type','normal'); - aeNode.setAttribute('url',element.url); - aeNode.setAttribute('gain',element.gain); + aeNode.setAttribute('ref', element.id); + if (typeof element.name == "string") { + aeNode.setAttribute('name', element.name); + } + aeNode.setAttribute('type', 'normal'); + aeNode.setAttribute('url', element.url); + aeNode.setAttribute('gain', element.gain); aeNode.appendChild(storage.document.createElement('metric')); root.appendChild(aeNode); // Build the 'X' element var audioObject = audioEngineContext.newTrack(element); var label; - switch(audioObject.specification.parent.label) { + switch (audioObject.specification.parent.label) { case "letter": label = "x"; break; @@ -434,98 +416,102 @@ label = "X"; break; } - var node = new this.interfaceObject(audioObject,label); + var node = new this.interfaceObject(audioObject, label); node.box.children[0].classList.add('inactive'); audioObject.bindInterface(node); this.X = node; this.boxHolders.appendChild(node.box); } -function resizeWindow(event) -{ - document.getElementById('submit').style.left = (window.innerWidth-250)/2 + 'px'; - var numObj = 3; - var boxW = numObj*312; +function resizeWindow(event) { + document.getElementById('submit').style.left = (window.innerWidth - 250) / 2 + 'px'; + var numObj = 3; + var boxW = numObj * 312; var diff = window.innerWidth - boxW; - while (diff < 0) - { - numObj = Math.ceil(numObj/2); - boxW = numObj*312; + while (diff < 0) { + numObj = Math.ceil(numObj / 2); + boxW = numObj * 312; diff = window.innerWidth - boxW; } - document.getElementById('box-holders').style.marginLeft = diff/2 + 'px'; - document.getElementById('box-holders').style.marginRight = diff/2 + 'px'; + document.getElementById('box-holders').style.marginLeft = diff / 2 + 'px'; + document.getElementById('box-holders').style.marginRight = diff / 2 + 'px'; document.getElementById('box-holders').style.width = boxW + 'px'; } -function buttonSubmitClick() -{ - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkFragmentsFullyPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); - break; - } +function buttonSubmitClick() { + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - if (canContinue) - { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Warning",'You have not started the test! Please listen to a sample to begin the test!'); - return; - } - } - testState.advanceState(); - } + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkFragmentsFullyPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Warning", 'You have not started the test! Please listen to a sample to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +}
--- a/interfaces/ape.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/ape.css Mon Nov 14 14:17:03 2016 +0000 @@ -2,103 +2,90 @@ * Hold any style information for APE interface. Customise if you like to make the interface your own! * */ + body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #ddd + /* Set the background colour (note US English spelling) to grey*/ + background-color: #ddd } - div.title { - /* Specify any colouring for the title */ + /* Specify any colouring for the title */ } - div.pageTitle { - width: auto; - height: 20px; - margin-top: 5px; - margin-bottom: 10px; + width: auto; + height: 20px; + margin-top: 5px; + margin-bottom: 10px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - div.slider { - /* Specify any structure for the slider holder interface */ - background-color: #eee; - height: 150px; - margin: 5px 50px; - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; + /* Specify any structure for the slider holder interface */ + background-color: #eee; + height: 150px; + margin: 5px 50px; + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; } - div.sliderScale { - width: 100%; - min-height: 30px; - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; + width: 100%; + min-height: 30px; + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; } - div.sliderScale span { - /* Any formatting of text below scale */ - font-size: 1.2em; - min-width: 5px; + /* Any formatting of text below scale */ + font-size: 1.2em; + min-width: 5px; max-width: 100px; text-align: center; - height: 20px; - position: absolute; + height: 20px; + position: absolute; } - div.track-slider { - /* Specify any structure for the slider objects */ - position: absolute; - height: inherit; - width: 12px; - float: left; - background-color: rgb(100,200,100); - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; + /* Specify any structure for the slider objects */ + position: absolute; + height: inherit; + width: 12px; + float: left; + background-color: rgb(100, 200, 100); + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; border: 1px solid black; } - div#outside-reference-holder { display: flex; align-content: center; justify-content: center; margin-bottom: 5px; } - div.outside-reference { - width:120px; + width: 120px; text-align: center; - height:20px; - background-color: rgb(100,200,100); + height: 20px; + background-color: rgb(100, 200, 100); position: inherit; margin: 0px 5px; } - div.track-slider-disabled { - background-color: rgb(100,100,100); + background-color: rgb(100, 100, 100); } - div.track-slider-playing { - background-color: #FF0000; + background-color: #FF0000; } - div.comment-box-playing { - background-color: #FFDDDD; + background-color: #FFDDDD; } - div#master-volume-holder { position: absolute; top: 10px; left: 120px; -} \ No newline at end of file +}
--- a/interfaces/ape.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/ape.js Mon Nov 14 14:17:03 2016 +0000 @@ -8,472 +8,440 @@ loadInterface(); function loadInterface() { - - // Get the dimensions of the screen available to the page - var width = window.innerWidth; - var height = window.innerHeight; - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - - testContent.id = 'testContent'; - - // Bindings for interfaceContext - interfaceContext.checkAllPlayed = function() - { - hasBeenPlayed = audioEngineContext.checkAllPlayed(); - if (hasBeenPlayed.length > 0) // if a fragment has not been played yet - { - var str = ""; - if (hasBeenPlayed.length > 1) { - for (var i=0; i<hasBeenPlayed.length; i++) { + + // Get the dimensions of the screen available to the page + var width = window.innerWidth; + var height = window.innerHeight; + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + + testContent.id = 'testContent'; + + // Bindings for interfaceContext + interfaceContext.checkAllPlayed = function () { + hasBeenPlayed = audioEngineContext.checkAllPlayed(); + if (hasBeenPlayed.length > 0) // if a fragment has not been played yet + { + var str = ""; + if (hasBeenPlayed.length > 1) { + for (var i = 0; i < hasBeenPlayed.length; i++) { var ao_id = audioEngineContext.audioObjects[hasBeenPlayed[i]].interfaceDOM.getPresentedId(); - str = str + ao_id; // start from 1 - if (i < hasBeenPlayed.length-2){ - str += ", "; - } else if (i == hasBeenPlayed.length-2) { - str += " or "; - } - } + str = str + ao_id; // start from 1 + if (i < hasBeenPlayed.length - 2) { + str += ", "; + } else if (i == hasBeenPlayed.length - 2) { + str += " or "; + } + } str = 'You have not played fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'; - } else { - str = 'You have not played fragment ' + (audioEngineContext.audioObjects[hasBeenPlayed[0]].interfaceDOM.getPresentedId()) + ' yet. Please listen, rate and comment all samples before submitting.'; - } + } else { + str = 'You have not played fragment ' + (audioEngineContext.audioObjects[hasBeenPlayed[0]].interfaceDOM.getPresentedId()) + ' yet. Please listen, rate and comment all samples before submitting.'; + } this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); - return false; - } - return true; - }; - - interfaceContext.checkAllMoved = function() { - var state = true; - var str = 'You have not moved the following sliders. '; - for (var i=0; i<this.interfaceSliders.length; i++) - { - var interfaceTID = []; - for (var j=0; j<this.interfaceSliders[i].metrics.length; j++) - { + interfaceContext.lightbox.post("Message", str); + return false; + } + return true; + }; + + interfaceContext.checkAllMoved = function () { + var state = true; + var str = 'You have not moved the following sliders. '; + for (var i = 0; i < this.interfaceSliders.length; i++) { + var interfaceTID = []; + for (var j = 0; j < this.interfaceSliders[i].metrics.length; j++) { var ao_id = this.interfaceSliders[i].sliders[j].getAttribute("trackIndex"); - if (this.interfaceSliders[i].metrics[j].wasMoved == false && audioEngineContext.audioObjects[ao_id].interfaceDOM.canMove()) - { - state = false; - interfaceTID.push(j); - } - } - if (interfaceTID.length != 0) - { - var interfaceName = this.interfaceSliders[i].interfaceObject.title; - if (interfaceName == undefined) { - str += 'On axis '+String(i+1)+' you must move '; - } else { - str += 'On axis "'+interfaceName+'" you must move '; - } - if (interfaceTID.length == 1) - { - str += 'slider '+(audioEngineContext.audioObjects[interfaceTID[0]].interfaceDOM.getPresentedId())+'. '; // start from 1 - } - else { - str += 'sliders '; - for (var k=0; k<interfaceTID.length-1; k++) - { - str += (audioEngineContext.audioObjects[interfaceTID[k]].interfaceDOM.getPresentedId())+', '; // start from 1 - } - str += (audioEngineContext.audioObjects[interfaceTID[interfaceTID.length-1]].interfaceDOM.getPresentedId()) +'. '; - } - } - } - if (state != true) - { + if (this.interfaceSliders[i].metrics[j].wasMoved == false && audioEngineContext.audioObjects[ao_id].interfaceDOM.canMove()) { + state = false; + interfaceTID.push(j); + } + } + if (interfaceTID.length != 0) { + var interfaceName = this.interfaceSliders[i].interfaceObject.title; + if (interfaceName == undefined) { + str += 'On axis ' + String(i + 1) + ' you must move '; + } else { + str += 'On axis "' + interfaceName + '" you must move '; + } + if (interfaceTID.length == 1) { + str += 'slider ' + (audioEngineContext.audioObjects[interfaceTID[0]].interfaceDOM.getPresentedId()) + '. '; // start from 1 + } else { + str += 'sliders '; + for (var k = 0; k < interfaceTID.length - 1; k++) { + str += (audioEngineContext.audioObjects[interfaceTID[k]].interfaceDOM.getPresentedId()) + ', '; // start from 1 + } + str += (audioEngineContext.audioObjects[interfaceTID[interfaceTID.length - 1]].interfaceDOM.getPresentedId()) + '. '; + } + } + } + if (state != true) { this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); - console.log(str); - } - return state; - }; - - Interface.prototype.checkAllCommented = function() { - var audioObjs = audioEngineContext.audioObjects; - var audioHolder = testState.stateMap[testState.stateIndex]; - var state = true; - if (audioHolder.elementComments) { - var strNums = []; - for (var i=0; i<audioObjs.length; i++) - { - if (audioObjs[i].commentDOM.trackCommentBox.value.length == 0) { - state = false; - strNums.push(i); - } - } - if (state == false) { + interfaceContext.lightbox.post("Message", str); + console.log(str); + } + return state; + }; + + Interface.prototype.checkAllCommented = function () { + var audioObjs = audioEngineContext.audioObjects; + var audioHolder = testState.stateMap[testState.stateIndex]; + var state = true; + if (audioHolder.elementComments) { + var strNums = []; + for (var i = 0; i < audioObjs.length; i++) { + if (audioObjs[i].commentDOM.trackCommentBox.value.length == 0) { + state = false; + strNums.push(i); + } + } + if (state == false) { var str = ""; - if (strNums.length > 1) { - - for (var i=0; i<strNums.length; i++) { + if (strNums.length > 1) { + + for (var i = 0; i < strNums.length; i++) { var ao_id = audioEngineContext.audioObjects[strNums[i]].interfaceDOM.getPresentedId(); - str = str + (ao_id); // start from 1 - if (i < strNums.length-2){ - str += ", "; - } else if (i == strNums.length-2) { - str += " or "; - } - } + str = str + (ao_id); // start from 1 + if (i < strNums.length - 2) { + str += ", "; + } else if (i == strNums.length - 2) { + str += " or "; + } + } str = 'You have not commented on fragments ' + str + ' yet. Please listen, rate and comment all samples before submitting.'; - } else { - str = 'You have not commented on fragment ' + (audioEngineContext.audioObjects[strNums[0]].interfaceDOM.getPresentedId()) + ' yet. Please listen, rate and comment all samples before submitting.'; - } + } else { + str = 'You have not commented on fragment ' + (audioEngineContext.audioObjects[strNums[0]].interfaceDOM.getPresentedId()) + ' yet. Please listen, rate and comment all samples before submitting.'; + } this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); + interfaceContext.lightbox.post("Message", str); console.log(str); - } - } - return state; - }; - - Interface.prototype.checkScaleRange = function() - { - var audioObjs = audioEngineContext.audioObjects; - var audioHolder = testState.stateMap[testState.stateIndex]; - var state = true; - var str = ''; - for (var i=0; i<this.interfaceSliders.length; i++) - { - var minScale; - var maxScale; - var interfaceObject = interfaceContext.interfaceSliders[0].interfaceObject; - for (var j=0; j<interfaceObject.options.length; j++) - { - if (interfaceObject.options[j].check == "scalerange") { - minScale = interfaceObject.options[j].min; - maxScale = interfaceObject.options[j].max; - break; - } - } - var minRanking = convSliderPosToRate(this.interfaceSliders[i].sliders[0]); - var maxRanking = minRanking; - for (var j=1; j<this.interfaceSliders[i].sliders.length; j++) - { - var ranking = convSliderPosToRate(this.interfaceSliders[i].sliders[j]); - if (ranking < minRanking) - { - minRanking = ranking; - } else if (ranking > maxRanking) - { - maxRanking = ranking; - } - } - if (minRanking > minScale || maxRanking < maxScale) - { - state = false; - str += 'On axis "'+this.interfaceSliders[i].interfaceObject.title+'" you have not used the full width of the scale. '; - } - } - if (state != true) - { + } + } + return state; + }; + + Interface.prototype.checkScaleRange = function () { + var audioObjs = audioEngineContext.audioObjects; + var audioHolder = testState.stateMap[testState.stateIndex]; + var state = true; + var str = ''; + for (var i = 0; i < this.interfaceSliders.length; i++) { + var minScale; + var maxScale; + var interfaceObject = interfaceContext.interfaceSliders[0].interfaceObject; + for (var j = 0; j < interfaceObject.options.length; j++) { + if (interfaceObject.options[j].check == "scalerange") { + minScale = interfaceObject.options[j].min; + maxScale = interfaceObject.options[j].max; + break; + } + } + var minRanking = convSliderPosToRate(this.interfaceSliders[i].sliders[0]); + var maxRanking = minRanking; + for (var j = 1; j < this.interfaceSliders[i].sliders.length; j++) { + var ranking = convSliderPosToRate(this.interfaceSliders[i].sliders[j]); + if (ranking < minRanking) { + minRanking = ranking; + } else if (ranking > maxRanking) { + maxRanking = ranking; + } + } + if (minRanking > minScale || maxRanking < maxScale) { + state = false; + str += 'On axis "' + this.interfaceSliders[i].interfaceObject.title + '" you have not used the full width of the scale. '; + } + } + if (state != true) { this.storeErrorNode(str); - interfaceContext.lightbox.post("Message",str); - console.log(str); - } - return state; - }; - - Interface.prototype.objectSelected = null; - Interface.prototype.objectMoved = false; - Interface.prototype.selectObject = function(object) - { - if (this.objectSelected == null) - { - this.objectSelected = object; - this.objectMoved = false; - } - }; - Interface.prototype.moveObject = function() - { - if (this.objectMoved == false) - { - this.objectMoved = true; - } - }; - Interface.prototype.releaseObject = function() - { - this.objectSelected = null; - this.objectMoved = false; - }; - Interface.prototype.getSelectedObject = function() - { - return this.objectSelected; - }; - Interface.prototype.hasSelectedObjectMoved = function() - { - return this.objectMoved; - }; - - // Bindings for slider interfaces - Interface.prototype.interfaceSliders = []; - - // Bindings for audioObjects - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + interfaceContext.lightbox.post("Message", str); + console.log(str); + } + return state; + }; + + Interface.prototype.objectSelected = null; + Interface.prototype.objectMoved = false; + Interface.prototype.selectObject = function (object) { + if (this.objectSelected == null) { + this.objectSelected = object; + this.objectMoved = false; + } + }; + Interface.prototype.moveObject = function () { + if (this.objectMoved == false) { + this.objectMoved = true; + } + }; + Interface.prototype.releaseObject = function () { + this.objectSelected = null; + this.objectMoved = false; + }; + Interface.prototype.getSelectedObject = function () { + return this.objectSelected; + }; + Interface.prototype.hasSelectedObjectMoved = function () { + return this.objectMoved; + }; + + // Bindings for slider interfaces + Interface.prototype.interfaceSliders = []; + + // Bindings for audioObjects + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // Insert the titleSpan element into the title div element. - title.appendChild(titleSpan); - - // Create Interface buttons! - var interfaceButtons = document.createElement('div'); - interfaceButtons.id = 'interface-buttons'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // Insert the titleSpan element into the title div element. + title.appendChild(titleSpan); + + // Create Interface buttons! + var interfaceButtons = document.createElement('div'); + interfaceButtons.id = 'interface-buttons'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Create Submit (save) button - var submit = document.createElement("button"); - submit.innerHTML = 'Next'; - submit.onclick = buttonSubmitClick; - submit.id = 'submit-button'; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - interfaceButtons.appendChild(submit); - - var sliderHolder = document.createElement("div"); - sliderHolder.id = "slider-holder"; - + } + }; + // Create Submit (save) button + var submit = document.createElement("button"); + submit.innerHTML = 'Next'; + submit.onclick = buttonSubmitClick; + submit.id = 'submit-button'; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + interfaceButtons.appendChild(submit); + + var sliderHolder = document.createElement("div"); + sliderHolder.id = "slider-holder"; + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - - testContent.style.zIndex = 1; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(interfaceButtons); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + + testContent.style.zIndex = 1; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(interfaceButtons); testContent.appendChild(outsideRef); - testContent.appendChild(sliderHolder); - testContent.appendChild(feedbackHolder); - interfaceContext.insertPoint.appendChild(testContent); + testContent.appendChild(sliderHolder); + testContent.appendChild(feedbackHolder); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); - + // Load the full interface + testState.initialise(); + testState.advanceState(); + } -function loadTest(audioHolderObject) -{ - var width = window.innerWidth; - var height = window.innerHeight; - var id = audioHolderObject.id; - - interfaceContext.interfaceSliders = []; - - var feedbackHolder = document.getElementById('feedbackHolder'); - var sliderHolder = document.getElementById('slider-holder'); - feedbackHolder.innerHTML = ""; - sliderHolder.innerHTML = ""; - +function loadTest(audioHolderObject) { + var width = window.innerWidth; + var height = window.innerHeight; + var id = audioHolderObject.id; + + interfaceContext.interfaceSliders = []; + + var feedbackHolder = document.getElementById('feedbackHolder'); + var sliderHolder = document.getElementById('slider-holder'); + feedbackHolder.innerHTML = ""; + sliderHolder.innerHTML = ""; + // Set the page title if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { document.getElementById("test-title").textContent = audioHolderObject.title } - - - // Delete outside reference - document.getElementById("outside-reference-holder").innerHTML = ""; - - var interfaceObj = audioHolderObject.interfaces; - for (var k=0; k<interfaceObj.length; k++) { - // Create the div box to center align - interfaceContext.interfaceSliders.push(new interfaceSliderHolder(interfaceObj[k])); - } - + + + // Delete outside reference + document.getElementById("outside-reference-holder").innerHTML = ""; + + var interfaceObj = audioHolderObject.interfaces; + for (var k = 0; k < interfaceObj.length; k++) { + // Create the div box to center align + interfaceContext.interfaceSliders.push(new interfaceSliderHolder(interfaceObj[k])); + } + var interfaceList = audioHolderObject.interfaces.concat(specification.interfaces); - for (var k=0; k<interfaceList.length; k++) - { - for (var i=0; i<interfaceList[k].options.length; i++) - { - if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') - { + for (var k = 0; k < interfaceList.length; k++) { + for (var i = 0; i < interfaceList[k].options.length; i++) { + if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') { var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.style.width = "100%"; playbackHolder.align = 'center'; playbackHolder.appendChild(interfaceContext.playhead.object); feedbackHolder.appendChild(playbackHolder); } - } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'page-count') - { + } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'page-count') { var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'volume') { - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'comments') { var commentHolder = document.createElement('div'); commentHolder.id = 'commentHolder'; document.getElementById('testContent').appendChild(commentHolder); - interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); break; } } } - - var commentBoxPrefix = "Comment on fragment"; - - var commentShow = audioHolderObject.elementComments; - - var loopPlayback = audioHolderObject.loop; - currentTestHolder = document.createElement('audioHolder'); - currentTestHolder.id = audioHolderObject.id; - currentTestHolder.repeatCount = audioHolderObject.repeatCount; - - // Find all the audioElements from the audioHolder - $(audioHolderObject.audioElements).each(function(index,element){ - // Find URL of track - // In this jQuery loop, variable 'this' holds the current audioElement. - var audioObject = audioEngineContext.newTrack(element); - // Check if an outside reference - if (element.type == 'outside-reference') - { - // Construct outside reference; - var orNode = new outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); - audioObject.bindInterface(orNode); - } else { - // Create a slider per track - var sliderNode = new sliderObject(audioObject,interfaceObj,index); - audioObject.bindInterface(sliderNode); + var commentBoxPrefix = "Comment on fragment"; + + var commentShow = audioHolderObject.elementComments; + + var loopPlayback = audioHolderObject.loop; + + currentTestHolder = document.createElement('audioHolder'); + currentTestHolder.id = audioHolderObject.id; + currentTestHolder.repeatCount = audioHolderObject.repeatCount; + + // Find all the audioElements from the audioHolder + $(audioHolderObject.audioElements).each(function (index, element) { + // Find URL of track + // In this jQuery loop, variable 'this' holds the current audioElement. + var audioObject = audioEngineContext.newTrack(element); + // Check if an outside reference + if (element.type == 'outside-reference') { + // Construct outside reference; + var orNode = new outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); + audioObject.bindInterface(orNode); + } else { + // Create a slider per track + var sliderNode = new sliderObject(audioObject, interfaceObj, index); + audioObject.bindInterface(sliderNode); interfaceContext.commentBoxes.createCommentBox(audioObject); - } - }); - - // Initialse the interfaceSlider object metrics - - $('.track-slider').mousedown(function(event) { - interfaceContext.selectObject($(this)[0]); - }); - $('.track-slider').on('touchstart',null,function(event) { - interfaceContext.selectObject($(this)[0]); - }); - - $('.track-slider').mousemove(function(event) { - event.preventDefault(); - }); - - $('.slider').mousemove(function(event) { - event.preventDefault(); - var obj = interfaceContext.getSelectedObject(); - if (obj == null) {return;} - var move = event.clientX-6; + } + }); + + // Initialse the interfaceSlider object metrics + + $('.track-slider').mousedown(function (event) { + interfaceContext.selectObject($(this)[0]); + }); + $('.track-slider').on('touchstart', null, function (event) { + interfaceContext.selectObject($(this)[0]); + }); + + $('.track-slider').mousemove(function (event) { + event.preventDefault(); + }); + + $('.slider').mousemove(function (event) { + event.preventDefault(); + var obj = interfaceContext.getSelectedObject(); + if (obj == null) { + return; + } + var move = event.clientX - 6; var w = $(event.currentTarget).width(); - move = Math.max(50,move); - move = Math.min(w+50,move); - $(obj).css("left",move + "px"); - interfaceContext.moveObject(); - }); - - $('.slider').on('touchmove',null,function(event) { - event.preventDefault(); - var obj = interfaceContext.getSelectedObject(); - if (obj == null) {return;} - var move = event.originalEvent.targetTouches[0].clientX - 6; + move = Math.max(50, move); + move = Math.min(w + 50, move); + $(obj).css("left", move + "px"); + interfaceContext.moveObject(); + }); + + $('.slider').on('touchmove', null, function (event) { + event.preventDefault(); + var obj = interfaceContext.getSelectedObject(); + if (obj == null) { + return; + } + var move = event.originalEvent.targetTouches[0].clientX - 6; var w = $(event.currentTarget).width(); - move = Math.max(50,move); - move = Math.min(w+50,move); - $(obj).css("left",move + "px"); - interfaceContext.moveObject(); - }); + move = Math.max(50, move); + move = Math.min(w + 50, move); + $(obj).css("left", move + "px"); + interfaceContext.moveObject(); + }); - $(document).mouseup(function(event){ - event.preventDefault(); - var obj = interfaceContext.getSelectedObject(); - if (obj == null) {return;} - var interfaceID = obj.parentElement.getAttribute("interfaceid"); - var trackID = obj.getAttribute("trackindex"); - if (interfaceContext.hasSelectedObjectMoved() == true) - { - var l = $(obj).css("left"); - var id = obj.getAttribute('trackIndex'); - var time = audioEngineContext.timer.getTestTime(); - var rate = convSliderPosToRate(obj); - audioEngineContext.audioObjects[id].metric.moved(time,rate); - interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time,rate); - console.log("slider "+id+" moved to "+rate+' ('+time+')'); - obj.setAttribute("slider-value",convSliderPosToRate(obj)); - } else { - var id = Number(obj.attributes['trackIndex'].value); - //audioEngineContext.metric.sliderPlayed(id); - audioEngineContext.play(id); - } - interfaceContext.releaseObject(); - }); - - $('.slider').on('touchend',null,function(event){ - var obj = interfaceContext.getSelectedObject(); - if (obj == null) {return;} - var interfaceID = obj.parentElement.getAttribute("interfaceid"); - var trackID = obj.getAttribute("trackindex"); - if (interfaceContext.hasSelectedObjectMoved() == true) - { - var l = $(obj).css("left"); - var id = obj.getAttribute('trackIndex'); - var time = audioEngineContext.timer.getTestTime(); - var rate = convSliderPosToRate(obj); - audioEngineContext.audioObjects[id].metric.moved(time,rate); - interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time,rate); - console.log("slider "+id+" moved to "+rate+' ('+time+')'); - } - interfaceContext.releaseObject(); - }); - + $(document).mouseup(function (event) { + event.preventDefault(); + var obj = interfaceContext.getSelectedObject(); + if (obj == null) { + return; + } + var interfaceID = obj.parentElement.getAttribute("interfaceid"); + var trackID = obj.getAttribute("trackindex"); + if (interfaceContext.hasSelectedObjectMoved() == true) { + var l = $(obj).css("left"); + var id = obj.getAttribute('trackIndex'); + var time = audioEngineContext.timer.getTestTime(); + var rate = convSliderPosToRate(obj); + audioEngineContext.audioObjects[id].metric.moved(time, rate); + interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time, rate); + console.log("slider " + id + " moved to " + rate + ' (' + time + ')'); + obj.setAttribute("slider-value", convSliderPosToRate(obj)); + } else { + var id = Number(obj.attributes['trackIndex'].value); + //audioEngineContext.metric.sliderPlayed(id); + audioEngineContext.play(id); + } + interfaceContext.releaseObject(); + }); + + $('.slider').on('touchend', null, function (event) { + var obj = interfaceContext.getSelectedObject(); + if (obj == null) { + return; + } + var interfaceID = obj.parentElement.getAttribute("interfaceid"); + var trackID = obj.getAttribute("trackindex"); + if (interfaceContext.hasSelectedObjectMoved() == true) { + var l = $(obj).css("left"); + var id = obj.getAttribute('trackIndex'); + var time = audioEngineContext.timer.getTestTime(); + var rate = convSliderPosToRate(obj); + audioEngineContext.audioObjects[id].metric.moved(time, rate); + interfaceContext.interfaceSliders[interfaceID].metrics[trackID].moved(time, rate); + console.log("slider " + id + " moved to " + rate + ' (' + time + ')'); + } + interfaceContext.releaseObject(); + }); + var interfaceList = audioHolderObject.interfaces.concat(specification.interfaces); - for (var k=0; k<interfaceList.length; k++) - { - for (var i=0; i<interfaceList[k].options.length; i++) - { - if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') - { + for (var k = 0; k < interfaceList.length; k++) { + for (var i = 0; i < interfaceList[k].options.length; i++) { + if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'playhead') { var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.id = "playback-holder"; playbackHolder.style.width = "100%"; @@ -481,162 +449,152 @@ playbackHolder.appendChild(interfaceContext.playhead.object); feedbackHolder.appendChild(playbackHolder); } - } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'page-count') - { + } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'page-count') { var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'volume') { - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } } else if (interfaceList[k].options[i].type == 'show' && interfaceList[k].options[i].name == 'comments') { - interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); break; } } } - - $(audioHolderObject.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - feedbackHolder.appendChild(node.holder); - }); - - //testWaitIndicator(); + + $(audioHolderObject.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + feedbackHolder.appendChild(node.holder); + }); + + //testWaitIndicator(); } -function interfaceSliderHolder(interfaceObject) -{ - this.sliders = []; - this.metrics = []; - this.id = document.getElementsByClassName("sliderCanvasDiv").length; - this.name = interfaceObject.name; - this.interfaceObject = interfaceObject; - this.sliderDOM = document.createElement('div'); - this.sliderDOM.className = 'sliderCanvasDiv'; - this.sliderDOM.id = 'sliderCanvasHolder-'+this.id; - - var pagetitle = document.createElement('div'); - pagetitle.className = "pageTitle"; - pagetitle.align = "center"; - var titleSpan = document.createElement('span'); - titleSpan.id = "pageTitle-"+this.id; - if (interfaceObject.title != undefined && typeof interfaceObject.title == "string") - { - titleSpan.textContent = interfaceObject.title; - } else { - titleSpan.textContent = "Axis "+String(this.id+1); - } - pagetitle.appendChild(titleSpan); - this.sliderDOM.appendChild(pagetitle); - - // Create the slider box to hold the slider elements - this.canvas = document.createElement('div'); - if (this.name != undefined) - this.canvas.id = 'slider-'+this.name; - else - this.canvas.id = 'slider-'+this.id; - this.canvas.setAttribute("interfaceid",this.id); - this.canvas.className = 'slider'; - this.canvas.align = "left"; - this.canvas.addEventListener('dragover',function(event){ - event.preventDefault(); - event.dataTransfer.effectAllowed = 'none'; - event.dataTransfer.dropEffect = 'copy'; - return false; - },false); - this.sliderDOM.appendChild(this.canvas); - - // Create the div to hold any scale objects - this.scale = document.createElement('div'); - this.scale.className = 'sliderScale'; - this.scale.id = 'sliderScaleHolder-'+this.id; - this.scale.align = 'left'; - this.sliderDOM.appendChild(this.scale); - var positionScale = this.canvas.style.width.substr(0,this.canvas.style.width.length-2); - var offset = 50; +function interfaceSliderHolder(interfaceObject) { + this.sliders = []; + this.metrics = []; + this.id = document.getElementsByClassName("sliderCanvasDiv").length; + this.name = interfaceObject.name; + this.interfaceObject = interfaceObject; + this.sliderDOM = document.createElement('div'); + this.sliderDOM.className = 'sliderCanvasDiv'; + this.sliderDOM.id = 'sliderCanvasHolder-' + this.id; + + var pagetitle = document.createElement('div'); + pagetitle.className = "pageTitle"; + pagetitle.align = "center"; + var titleSpan = document.createElement('span'); + titleSpan.id = "pageTitle-" + this.id; + if (interfaceObject.title != undefined && typeof interfaceObject.title == "string") { + titleSpan.textContent = interfaceObject.title; + } else { + titleSpan.textContent = "Axis " + String(this.id + 1); + } + pagetitle.appendChild(titleSpan); + this.sliderDOM.appendChild(pagetitle); + + // Create the slider box to hold the slider elements + this.canvas = document.createElement('div'); + if (this.name != undefined) + this.canvas.id = 'slider-' + this.name; + else + this.canvas.id = 'slider-' + this.id; + this.canvas.setAttribute("interfaceid", this.id); + this.canvas.className = 'slider'; + this.canvas.align = "left"; + this.canvas.addEventListener('dragover', function (event) { + event.preventDefault(); + event.dataTransfer.effectAllowed = 'none'; + event.dataTransfer.dropEffect = 'copy'; + return false; + }, false); + this.sliderDOM.appendChild(this.canvas); + + // Create the div to hold any scale objects + this.scale = document.createElement('div'); + this.scale.className = 'sliderScale'; + this.scale.id = 'sliderScaleHolder-' + this.id; + this.scale.align = 'left'; + this.sliderDOM.appendChild(this.scale); + var positionScale = this.canvas.style.width.substr(0, this.canvas.style.width.length - 2); + var offset = 50; var dest = document.getElementById("slider-holder").appendChild(this.sliderDOM); - for (var scaleObj of interfaceObject.scales) - { - var position = Number(scaleObj.position)*0.01; - var pixelPosition = (position*$(this.canvas).width())+offset; - var scaleDOM = document.createElement('span'); + for (var scaleObj of interfaceObject.scales) { + var position = Number(scaleObj.position) * 0.01; + var pixelPosition = (position * $(this.canvas).width()) + offset; + var scaleDOM = document.createElement('span'); scaleDOM.className = "ape-marker-text"; - scaleDOM.textContent = scaleObj.text; - scaleDOM.setAttribute('value',position) - this.scale.appendChild(scaleDOM); - scaleDOM.style.left = Math.floor((pixelPosition-($(scaleDOM).width()/2)))+'px'; - } - - this.createSliderObject = function(audioObject,label) - { - var trackObj = document.createElement('div'); + scaleDOM.textContent = scaleObj.text; + scaleDOM.setAttribute('value', position) + this.scale.appendChild(scaleDOM); + scaleDOM.style.left = Math.floor((pixelPosition - ($(scaleDOM).width() / 2))) + 'px'; + } + + this.createSliderObject = function (audioObject, label) { + var trackObj = document.createElement('div'); trackObj.align = "center"; - trackObj.className = 'track-slider track-slider-disabled track-slider-'+audioObject.id; - trackObj.id = 'track-slider-'+this.id+'-'+audioObject.id; - trackObj.setAttribute('trackIndex',audioObject.id); - if (this.name != undefined) { - trackObj.setAttribute('interface-name',this.name); - } else { - trackObj.setAttribute('interface-name',this.id); - } - var offset = 50; - // 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'; - this.canvas.appendChild(trackObj); - this.sliders.push(trackObj); - this.metrics.push(new metricTracker(this)); - var labelHolder = document.createElement("span"); + trackObj.className = 'track-slider track-slider-disabled track-slider-' + audioObject.id; + trackObj.id = 'track-slider-' + this.id + '-' + audioObject.id; + trackObj.setAttribute('trackIndex', audioObject.id); + if (this.name != undefined) { + trackObj.setAttribute('interface-name', this.name); + } else { + trackObj.setAttribute('interface-name', this.id); + } + var offset = 50; + // 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'; + this.canvas.appendChild(trackObj); + this.sliders.push(trackObj); + this.metrics.push(new metricTracker(this)); + var labelHolder = document.createElement("span"); labelHolder.textContent = label; trackObj.appendChild(labelHolder); var rate = convSliderPosToRate(trackObj); - this.metrics[this.metrics.length-1].initialise(rate); - trackObj.setAttribute("slider-value",rate); - return trackObj; - }; - - this.resize = function(event) - { - var width = window.innerWidth; - var sliderDiv = this.canvas; - var sliderScaleDiv = this.scale; - var width = $(sliderDiv).width(); + this.metrics[this.metrics.length - 1].initialise(rate); + trackObj.setAttribute("slider-value", rate); + return trackObj; + }; + + this.resize = function (event) { + var width = window.innerWidth; + var sliderDiv = this.canvas; + var sliderScaleDiv = this.scale; + var width = $(sliderDiv).width(); var marginsize = 50; - // Move sliders into new position - for (var index = 0; index < this.sliders.length; index++) - { - var pix = Number(this.sliders[index].getAttribute("slider-value")) * width; - this.sliders[index].style.left = (pix+marginsize)+'px'; - } - - // Move scale labels - for (var index = 0; index < this.scale.children.length; index++) - { - var scaleObj = this.scale.children[index]; - var position = Number(scaleObj.attributes['value'].value); - var pixelPosition = (position*width)+marginsize; - scaleObj.style.left = Math.floor((pixelPosition-($(scaleObj).width()/2)))+'px'; - } - }; + // Move sliders into new position + for (var index = 0; index < this.sliders.length; index++) { + var pix = Number(this.sliders[index].getAttribute("slider-value")) * width; + this.sliders[index].style.left = (pix + marginsize) + 'px'; + } + + // Move scale labels + for (var index = 0; index < this.scale.children.length; index++) { + var scaleObj = this.scale.children[index]; + var position = Number(scaleObj.attributes['value'].value); + var pixelPosition = (position * width) + marginsize; + scaleObj.style.left = Math.floor((pixelPosition - ($(scaleObj).width() / 2))) + 'px'; + } + }; } -function sliderObject(audioObject,interfaceObjects,index) { - // Create a new slider object; - this.parent = audioObject; - this.trackSliderObjects = []; +function sliderObject(audioObject, interfaceObjects, index) { + // Create a new slider object; + this.parent = audioObject; + this.trackSliderObjects = []; this.label = null; this.playing = false; - switch(audioObject.specification.parent.label) { + switch (audioObject.specification.parent.label) { case "letter": this.label = String.fromCharCode(97 + index); break; @@ -647,295 +605,277 @@ this.label = ""; break; default: - this.label = ""+(index+1); + this.label = "" + (index + 1); break; } - for (var i=0; i<interfaceContext.interfaceSliders.length; i++) - { - var trackObj = interfaceContext.interfaceSliders[i].createSliderObject(audioObject,this.label); - this.trackSliderObjects.push(trackObj); - } + for (var i = 0; i < interfaceContext.interfaceSliders.length; i++) { + var trackObj = interfaceContext.interfaceSliders[i].createSliderObject(audioObject, this.label); + this.trackSliderObjects.push(trackObj); + } - // Onclick, switch playback to that track - - this.enable = function() { - if (this.parent.state == 1) - { - $(this.trackSliderObjects).each(function(i,trackObj){ - $(trackObj).removeClass('track-slider-disabled'); - }); - } - }; - this.updateLoading = function(progress) - { - if (progress != 100) - { - progress = String(progress); - progress = progress.split('.')[0]; - this.trackSliderObjects[0].children[0].textContent = progress+'%'; - } else { - this.trackSliderObjects[0].children[0].textContent = this.label; - } - }; - this.startPlayback = function() - { + // Onclick, switch playback to that track + + this.enable = function () { + if (this.parent.state == 1) { + $(this.trackSliderObjects).each(function (i, trackObj) { + $(trackObj).removeClass('track-slider-disabled'); + }); + } + }; + this.updateLoading = function (progress) { + if (progress != 100) { + progress = String(progress); + progress = progress.split('.')[0]; + this.trackSliderObjects[0].children[0].textContent = progress + '%'; + } else { + this.trackSliderObjects[0].children[0].textContent = this.label; + } + }; + this.startPlayback = function () { $('.track-slider').removeClass('track-slider-playing'); - var name = ".track-slider-"+this.parent.id; + var name = ".track-slider-" + this.parent.id; $(name).addClass('track-slider-playing'); $('.comment-div').removeClass('comment-box-playing'); - $('#comment-div-'+this.parent.id).addClass('comment-box-playing'); + $('#comment-div-' + this.parent.id).addClass('comment-box-playing'); $('.outside-reference').removeClass('track-slider-playing'); this.playing = true; - + if (this.parent.specification.parent.playOne || specification.playOne) { $('.track-slider').addClass('track-slider-disabled'); $('.outside-reference').addClass('track-slider-disabled'); } }; - this.stopPlayback = function() - { + this.stopPlayback = function () { if (this.playing) { this.playing = false; - var name = ".track-slider-"+this.parent.id; + var name = ".track-slider-" + this.parent.id; $(name).removeClass('track-slider-playing'); - $('#comment-div-'+this.parent.id).removeClass('comment-box-playing'); + $('#comment-div-' + this.parent.id).removeClass('comment-box-playing'); $('.track-slider').removeClass('track-slider-disabled'); $('.outside-reference').removeClass('track-slider-disabled'); } }; - this.exportXMLDOM = function(audioObject) { - // Called by the audioObject holding this element. Must be present - var obj = []; - $(this.trackSliderObjects).each(function(i,trackObj){ - var node = storage.document.createElement('value'); - node.setAttribute("interface-name",trackObj.getAttribute("interface-name")); - node.textContent = convSliderPosToRate(trackObj); - obj.push(node); - }); - - return obj; - }; - this.getValue = function() { - return convSliderPosToRate(this.trackSliderObjects[0]); - }; - this.getPresentedId = function() - { - return this.label; - }; - this.canMove = function() - { - return true; - }; - this.error = function() { - // audioObject has an error!! + this.exportXMLDOM = function (audioObject) { + // Called by the audioObject holding this element. Must be present + var obj = []; + $(this.trackSliderObjects).each(function (i, trackObj) { + var node = storage.document.createElement('value'); + node.setAttribute("interface-name", trackObj.getAttribute("interface-name")); + node.textContent = convSliderPosToRate(trackObj); + obj.push(node); + }); + + return obj; + }; + this.getValue = function () { + return convSliderPosToRate(this.trackSliderObjects[0]); + }; + this.getPresentedId = function () { + return this.label; + }; + this.canMove = function () { + return true; + }; + this.error = function () { + // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } } -function outsideReferenceDOM(audioObject,index,inject) -{ - this.parent = audioObject; - this.outsideReferenceHolder = document.createElement('div'); - this.outsideReferenceHolder.id = 'outside-reference'; - this.outsideReferenceHolder.className = 'outside-reference track-slider-disabled'; - var outsideReferenceHolderspan = document.createElement('span'); - outsideReferenceHolderspan.textContent = 'Reference'; - this.outsideReferenceHolder.appendChild(outsideReferenceHolderspan); - this.outsideReferenceHolder.setAttribute('track-id',index); - - this.outsideReferenceHolder.onclick = function(event) - { - audioEngineContext.play(event.currentTarget.getAttribute('track-id')); - $('.track-slider').removeClass('track-slider-playing'); +function outsideReferenceDOM(audioObject, index, inject) { + this.parent = audioObject; + this.outsideReferenceHolder = document.createElement('div'); + this.outsideReferenceHolder.id = 'outside-reference'; + this.outsideReferenceHolder.className = 'outside-reference track-slider-disabled'; + var outsideReferenceHolderspan = document.createElement('span'); + outsideReferenceHolderspan.textContent = 'Reference'; + this.outsideReferenceHolder.appendChild(outsideReferenceHolderspan); + this.outsideReferenceHolder.setAttribute('track-id', index); + + this.outsideReferenceHolder.onclick = function (event) { + audioEngineContext.play(event.currentTarget.getAttribute('track-id')); + $('.track-slider').removeClass('track-slider-playing'); $('.comment-div').removeClass('comment-box-playing'); if (event.currentTarget.nodeName == 'DIV') { - $(event.currentTarget).addClass('track-slider-playing'); + $(event.currentTarget).addClass('track-slider-playing'); } else { - $(event.currentTarget.parentElement).addClass('track-slider-playing'); + $(event.currentTarget.parentElement).addClass('track-slider-playing'); } - }; - inject.appendChild(this.outsideReferenceHolder); - this.enable = function() - { - if (this.parent.state == 1) - { - $(this.outsideReferenceHolder).removeClass('track-slider-disabled'); - } - }; - this.updateLoading = function(progress) - { - if (progress != 100) - { - progress = String(progress); - progress = progress.split('.')[0]; - this.outsideReferenceHolder.firstChild.textContent = progress+'%'; - } else { - this.outsideReferenceHolder.firstChild.textContent = "Play Reference"; - } - }; - this.startPlayback = function() - { + }; + inject.appendChild(this.outsideReferenceHolder); + this.enable = function () { + if (this.parent.state == 1) { + $(this.outsideReferenceHolder).removeClass('track-slider-disabled'); + } + }; + this.updateLoading = function (progress) { + if (progress != 100) { + progress = String(progress); + progress = progress.split('.')[0]; + this.outsideReferenceHolder.firstChild.textContent = progress + '%'; + } else { + this.outsideReferenceHolder.firstChild.textContent = "Play Reference"; + } + }; + this.startPlayback = function () { $('.track-slider').removeClass('track-slider-playing'); $(this.outsideReferenceHolder).addClass('track-slider-playing'); $('.comment-div').removeClass('comment-box-playing'); }; - this.stopPlayback = function() - { + this.stopPlayback = function () { $(this.outsideReferenceHolder).removeClass('track-slider-playing'); }; - this.exportXMLDOM = function(audioObject) - { - return null; - }; - this.getValue = function() - { - return 0; - }; - this.getPresentedId = function() - { - return 'reference'; - }; - this.canMove = function() - { - return false; - }; - this.error = function() { - // audioObject has an error!! + this.exportXMLDOM = function (audioObject) { + return null; + }; + this.getValue = function () { + return 0; + }; + this.getPresentedId = function () { + return 'reference'; + }; + this.canMove = function () { + return false; + }; + this.error = function () { + // audioObject has an error!! this.outsideReferenceHolder.textContent = "Error"; $(this.outsideReferenceHolder).addClass("error-colour"); } } -function buttonSubmitClick() -{ - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - // Check that the anchor and reference objects are correctly placed - if (interfaceContext.checkHiddenAnchor() == false) {return;} - if (interfaceContext.checkHiddenReference() == false) {return;} - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkFragmentsFullyPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale is used to its full width outlined by the node - var checkState = interfaceContext.checkScaleRange(); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].name+" is not supported on this interface"); - break; - } +function buttonSubmitClick() { + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - + // Check that the anchor and reference objects are correctly placed + if (interfaceContext.checkHiddenAnchor() == false) { + return; + } + if (interfaceContext.checkHiddenReference() == false) { + return; + } + + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkFragmentsFullyPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale is used to its full width outlined by the node + var checkState = interfaceContext.checkScaleRange(); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].name + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Warning",'You have not started the test! Please click a fragment to begin the test!'); - return; - } - } - testState.advanceState(); - } + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Warning", 'You have not started the test! Please click a fragment to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function convSliderPosToRate(trackSlider) -{ - var slider = trackSlider.parentElement; - var maxPix = $(slider).width(); - var marginsize = 50; - var pix = trackSlider.style.left; - pix = pix.substr(0,pix.length-2); - var rate = (pix-marginsize)/maxPix; - return rate; +function convSliderPosToRate(trackSlider) { + var slider = trackSlider.parentElement; + var maxPix = $(slider).width(); + var marginsize = 50; + var pix = trackSlider.style.left; + pix = pix.substr(0, pix.length - 2); + var rate = (pix - marginsize) / maxPix; + return rate; } -function resizeWindow(event){ - // Function called when the window has been resized. - // MANDATORY FUNCTION - - // Resize the slider objects - for (var i=0; i<interfaceContext.interfaceSliders.length; i++) - { - interfaceContext.interfaceSliders[i].resize(event); - } +function resizeWindow(event) { + // Function called when the window has been resized. + // MANDATORY FUNCTION + + // Resize the slider objects + for (var i = 0; i < interfaceContext.interfaceSliders.length; i++) { + interfaceContext.interfaceSliders[i].resize(event); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); - - if (interfaceContext.interfaceSliders.length == 1) - { - // If there is only one axis, there only needs to be one metric return - return; - } - var audioelements = store.getElementsByTagName("audioelement"); - for (var i=0; i<audioelements.length; i++) - { - // Have to append the metric specific nodes - if (pageSpecification.outsideReference == null || pageSpecification.outsideReference.id != audioelements[i].id) - { - var inject = audioelements[i].getElementsByTagName("metric"); - if (inject.length == 0) - { - inject = storage.document.createElement("metric"); - } else { - inject = inject[0]; - } - for (var k=0; k<interfaceContext.interfaceSliders.length; k++) - { - var mrnodes = interfaceContext.interfaceSliders[k].metrics[i].exportXMLDOM(inject); - for (var j=0; j<mrnodes.length; j++) - { - var name = mrnodes[j].getAttribute("name"); - if (name == "elementTracker" || name == "elementTrackerFull" || name == "elementInitialPosition" || name == "elementFlagMoved") - { - mrnodes[j].setAttribute("interface-name",interfaceContext.interfaceSliders[k].name); - mrnodes[j].setAttribute("interface-id",k); - inject.appendChild(mrnodes[j]); - } - } - } - } - } -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); + + if (interfaceContext.interfaceSliders.length == 1) { + // If there is only one axis, there only needs to be one metric return + return; + } + var audioelements = store.getElementsByTagName("audioelement"); + for (var i = 0; i < audioelements.length; i++) { + // Have to append the metric specific nodes + if (pageSpecification.outsideReference == null || pageSpecification.outsideReference.id != audioelements[i].id) { + var inject = audioelements[i].getElementsByTagName("metric"); + if (inject.length == 0) { + inject = storage.document.createElement("metric"); + } else { + inject = inject[0]; + } + for (var k = 0; k < interfaceContext.interfaceSliders.length; k++) { + var mrnodes = interfaceContext.interfaceSliders[k].metrics[i].exportXMLDOM(inject); + for (var j = 0; j < mrnodes.length; j++) { + var name = mrnodes[j].getAttribute("name"); + if (name == "elementTracker" || name == "elementTrackerFull" || name == "elementInitialPosition" || name == "elementFlagMoved") { + mrnodes[j].setAttribute("interface-name", interfaceContext.interfaceSliders[k].name); + mrnodes[j].setAttribute("interface-id", k); + inject.appendChild(mrnodes[j]); + } + } + } + } + } +}
--- a/interfaces/blank.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/blank.js Mon Nov 14 14:17:03 2016 +0000 @@ -7,72 +7,61 @@ loadInterface(); function loadInterface() { - // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, - // holding div's, or setting up any nodes which are present for the entire test sequence + // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, + // holding div's, or setting up any nodes which are present for the entire test sequence }; -function loadTest(page) -{ - // Called each time a new test page is to be build. The page specification node is the only item passed in +function loadTest(page) { + // Called each time a new test page is to be build. The page specification node is the only item passed in } -function interfaceObject() -{ - // An example node, you can make this however you want for each audioElement. - // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following - // You attach them by calling audioObject.bindInterface( ) - this.enable = function() - { - // This is used to tell the interface object that playback of this node is ready - }; - this.updateLoading = function(progress) - { - // progress is a value from 0 to 100 indicating the current download state of media files - }; - this.startPlayback = function() - { +function interfaceObject() { + // An example node, you can make this however you want for each audioElement. + // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following + // You attach them by calling audioObject.bindInterface( ) + this.enable = function () { + // This is used to tell the interface object that playback of this node is ready + }; + this.updateLoading = function (progress) { + // progress is a value from 0 to 100 indicating the current download state of media files + }; + this.startPlayback = function () { // Called when playback has begun }; - this.stopPlayback = function() - { + this.stopPlayback = function () { // Called when playback has stopped. This gets called even if playback never started! }; - this.getValue = function() - { - // Return the current value of the object. If there is no value, return 0 - }; - this.getPresentedId = function() - { - // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale - }; - this.canMove = function() - { - // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. - // These are checked primarily if the interface check option 'fragmentMoved' is enabled. - }; - this.exportXMLDOM = function(audioObject) { - // Called by the audioObject holding this element to export the interface <value> node. - // If there is no value node (such as outside reference), return null - // 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 - // Use storage.document.createElement('value'); to generate the XML node. - - }; - this.error = function() { + this.getValue = function () { + // Return the current value of the object. If there is no value, return 0 + }; + this.getPresentedId = function () { + // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale + }; + this.canMove = function () { + // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. + // These are checked primarily if the interface check option 'fragmentMoved' is enabled. + }; + this.exportXMLDOM = function (audioObject) { + // Called by the audioObject holding this element to export the interface <value> node. + // If there is no value node (such as outside reference), return null + // 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 + // Use storage.document.createElement('value'); to generate the XML node. + + }; + this.error = function () { // If there is an error with the audioObject, this will be called to indicate a failure } }; -function resizeWindow(event) -{ - // Called on every window resize event, use this to scale your page properly +function resizeWindow(event) { + // Called on every window resize event, use this to scale your page properly } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +}
--- a/interfaces/discrete.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/discrete.css Mon Nov 14 14:17:03 2016 +0000 @@ -2,113 +2,97 @@ * Hold any style information for MUSHRA interface. Customise if you like to make the interface your own! * */ + body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #ddd + /* Set the background colour (note US English spelling) to grey*/ + background-color: #ddd } - div.pageTitle { - width: auto; - height: 20px; - margin: 10px 0px; + width: auto; + height: 20px; + margin: 10px 0px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - div#slider-holder { - height: inherit; - position: absolute; - left: 0px; - z-index: 3; - margin-top:25px; + height: inherit; + position: absolute; + left: 0px; + z-index: 3; + margin-top: 25px; } - div#scale-holder { - position: absolute; - left: 0px; - z-index: 2; + position: absolute; + left: 0px; + z-index: 2; } - div#scale-text-holder { - position:relative; - float: left; + position: relative; + float: left; } div.scale-text { - position: absolute; - font-size: 1.2em; + position: absolute; + font-size: 1.2em; } - canvas#scale-canvas { - position: relative; - float: left; + position: relative; + float: left; } - div.track-slider { - float: left; - height: 30px; - border: solid; - border-width: 1px; - border-color: black; - padding:2px; - margin-left: 94px; - margin-bottom: 30px; + float: left; + height: 30px; + border: solid; + border-width: 1px; + border-color: black; + padding: 2px; + margin-left: 94px; + margin-bottom: 30px; } - div.track-slider-range { - float: left; - height: 100%; - margin: 0px 50px; - position: relative; + float: left; + height: 100%; + margin: 0px 50px; + position: relative; } - div.track-slider-title { - float: left; - padding-top: 5px; - width: 100px; + float: left; + padding-top: 5px; + width: 100px; } - button.track-slider-button { - float: left; - width: 100px; - height: 30px; + float: left; + width: 100px; + height: 30px; } - input.track-radio { - position: absolute; - margin: 9px 0px; + position: absolute; + margin: 9px 0px; } - div#outside-reference-holder { display: flex; align-content: center; justify-content: center; margin-bottom: 5px; } - button.outside-reference { position: inherit; margin: 0px 5px; } - div.track-slider-playing { - background-color: #FFDDDD; + background-color: #FFDDDD; } - div#page-count { float: left; margin: 0px 5px; } - div#master-volume-holder { position: absolute; top: 10px; left: 120px; -} \ No newline at end of file +}
--- a/interfaces/discrete.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/discrete.js Mon Nov 14 14:17:03 2016 +0000 @@ -2,170 +2,166 @@ loadInterface(); function loadInterface() { - // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, - // holding div's, or setting up any nodes which are present for the entire test sequence - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, + // holding div's, or setting up any nodes which are present for the entire test sequence + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // 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'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // 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'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - + } + }; + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - // Create Submit (save) button - var submit = document.createElement("button"); - submit.innerHTML = 'Next'; - submit.onclick = buttonSubmitClick; - submit.id = 'submit-button'; - submit.style.float = 'left'; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - interfaceButtons.appendChild(submit); - - // Create a slider box - var sliderBox = document.createElement('div'); - sliderBox.style.width = "100%"; - sliderBox.style.height = window.innerHeight - 200+12 + 'px'; - sliderBox.style.marginBottom = '10px'; - sliderBox.id = 'slider'; - var scaleHolder = document.createElement('div'); - scaleHolder.id = "scale-holder"; - scaleHolder.style.marginLeft = "107px"; - sliderBox.appendChild(scaleHolder); - var scaleText = document.createElement('div'); - scaleText.id = "scale-text-holder"; - scaleText.style.height = "25px"; - scaleText.style.width = "100%"; - scaleHolder.appendChild(scaleText); - var scaleCanvas = document.createElement('canvas'); - scaleCanvas.id = "scale-canvas"; - scaleCanvas.style.marginLeft = "150px"; - scaleHolder.appendChild(scaleCanvas); - var sliderObjectHolder = document.createElement('div'); - sliderObjectHolder.id = 'slider-holder'; - sliderObjectHolder.align = "center"; - sliderBox.appendChild(sliderObjectHolder); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - - testContent.style.zIndex = 1; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); + + // Create Submit (save) button + var submit = document.createElement("button"); + submit.innerHTML = 'Next'; + submit.onclick = buttonSubmitClick; + submit.id = 'submit-button'; + submit.style.float = 'left'; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + interfaceButtons.appendChild(submit); + + // Create a slider box + var sliderBox = document.createElement('div'); + sliderBox.style.width = "100%"; + sliderBox.style.height = window.innerHeight - 200 + 12 + 'px'; + sliderBox.style.marginBottom = '10px'; + sliderBox.id = 'slider'; + var scaleHolder = document.createElement('div'); + scaleHolder.id = "scale-holder"; + scaleHolder.style.marginLeft = "107px"; + sliderBox.appendChild(scaleHolder); + var scaleText = document.createElement('div'); + scaleText.id = "scale-text-holder"; + scaleText.style.height = "25px"; + scaleText.style.width = "100%"; + scaleHolder.appendChild(scaleText); + var scaleCanvas = document.createElement('canvas'); + scaleCanvas.id = "scale-canvas"; + scaleCanvas.style.marginLeft = "150px"; + scaleHolder.appendChild(scaleCanvas); + var sliderObjectHolder = document.createElement('div'); + sliderObjectHolder.id = 'slider-holder'; + sliderObjectHolder.align = "center"; + sliderBox.appendChild(sliderObjectHolder); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + + testContent.style.zIndex = 1; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); testContent.appendChild(outsideRef); - testContent.appendChild(sliderBox); - testContent.appendChild(feedbackHolder); - interfaceContext.insertPoint.appendChild(testContent); + testContent.appendChild(sliderBox); + testContent.appendChild(feedbackHolder); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); }; -function loadTest(page) -{ - // Called each time a new test page is to be build. The page specification node is the only item passed in - var id = page.id; - - var feedbackHolder = document.getElementById('feedbackHolder'); +function loadTest(page) { + // Called each time a new test page is to be build. The page specification node is the only item passed in + var id = page.id; + + var feedbackHolder = document.getElementById('feedbackHolder'); feedbackHolder.innerHTML = ""; - var interfaceObj = page.interfaces; - if (interfaceObj.length > 1) - { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - + var interfaceObj = page.interfaces; + if (interfaceObj.length > 1) { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + // Set the page title if (typeof page.title == "string" && page.title.length > 0) { document.getElementById("test-title").textContent = page.title } - - if(interfaceObj.title != null) - { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - - // Delete outside reference + + if (interfaceObj.title != null) { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + + // Delete outside reference document.getElementById("outside-reference-holder").innerHTML = ""; - - var sliderBox = document.getElementById('slider-holder'); - sliderBox.innerHTML = ""; - - var commentBoxPrefix = "Comment on track"; - if (interfaceObj.commentBoxPrefix != undefined) { - commentBoxPrefix = interfaceObj.commentBoxPrefix; - } - var loopPlayback = page.loop; - - // Find all the audioElements from the audioHolder - var index = 0; - var interfaceScales = testState.currentStateMap.interfaces[0].scales; - $(page.audioElements).each(function(index,element){ - // Find URL of track - // In this jQuery loop, variable 'this' holds the current audioElement. - - var audioObject = audioEngineContext.newTrack(element); - if (element.type == 'outside-reference') - { - // Construct outside reference; - var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); - audioObject.bindInterface(orNode); - } else { - // Create a slider per track - switch(audioObject.specification.parent.label) { + + var sliderBox = document.getElementById('slider-holder'); + sliderBox.innerHTML = ""; + + var commentBoxPrefix = "Comment on track"; + if (interfaceObj.commentBoxPrefix != undefined) { + commentBoxPrefix = interfaceObj.commentBoxPrefix; + } + var loopPlayback = page.loop; + + // Find all the audioElements from the audioHolder + var index = 0; + var interfaceScales = testState.currentStateMap.interfaces[0].scales; + $(page.audioElements).each(function (index, element) { + // Find URL of track + // In this jQuery loop, variable 'this' holds the current audioElement. + + var audioObject = audioEngineContext.newTrack(element); + if (element.type == 'outside-reference') { + // Construct outside reference; + var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); + audioObject.bindInterface(orNode); + } else { + // Create a slider per track + switch (audioObject.specification.parent.label) { case "none": label = ""; break; @@ -176,28 +172,25 @@ label = String.fromCharCode(65 + index); break; default: - label = ""+index; + label = "" + index; break; } - var sliderObj = new discreteObject(audioObject,label,interfaceScales); - sliderBox.appendChild(sliderObj.holder); - audioObject.bindInterface(sliderObj); + var sliderObj = new discreteObject(audioObject, label, interfaceScales); + sliderBox.appendChild(sliderObj.holder); + audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - index += 1; - } - - }); - + index += 1; + } + + }); + var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); - for (var option of interfaceOptions) - { - if (option.type == "show") - { - switch(option.name) { + for (var option of interfaceOptions) { + if (option.type == "show") { + switch (option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.style.width = "100%"; playbackHolder.align = 'center'; @@ -207,350 +200,341 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); break; case "volume": - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": - interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); break; } } } - - $(page.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - feedbackHolder.appendChild(node.holder); - }); - - // Auto-align - resizeWindow(null); + + $(page.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + feedbackHolder.appendChild(node.holder); + }); + + // Auto-align + resizeWindow(null); } -function discreteObject(audioObject,label,interfaceScales) -{ - // An example node, you can make this however you want for each audioElement. - // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following - // You attach them by calling audioObject.bindInterface( ) - if (interfaceScales == null || interfaceScales.length == 0) - { - console.log("WARNING: The discrete radio's are built depending on the number of scale points specified! Ensure you have some specified. Defaulting to 5 for now!"); - numOptions = 5; - } - this.parent = audioObject; - - this.holder = document.createElement('div'); - this.title = document.createElement('div'); - this.discreteHolder = document.createElement('div'); - this.discretes = []; - this.play = document.createElement('button'); - - this.holder.className = 'track-slider'; - this.holder.style.width = window.innerWidth-200 + 'px'; - this.holder.appendChild(this.title); - this.holder.appendChild(this.discreteHolder); - this.holder.appendChild(this.play); - this.holder.setAttribute('trackIndex',audioObject.id); - this.title.textContent = label; - this.title.className = 'track-slider-title'; - - this.discreteHolder.className = "track-slider-range"; - this.discreteHolder.style.width = window.innerWidth-500 + 'px'; - for (var i=0; i<interfaceScales.length; i++) - { - var node = document.createElement('input'); - node.setAttribute('type','radio'); - node.className = 'track-radio'; +function discreteObject(audioObject, label, interfaceScales) { + // An example node, you can make this however you want for each audioElement. + // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following + // You attach them by calling audioObject.bindInterface( ) + if (interfaceScales == null || interfaceScales.length == 0) { + console.log("WARNING: The discrete radio's are built depending on the number of scale points specified! Ensure you have some specified. Defaulting to 5 for now!"); + numOptions = 5; + } + this.parent = audioObject; + + this.holder = document.createElement('div'); + this.title = document.createElement('div'); + this.discreteHolder = document.createElement('div'); + this.discretes = []; + this.play = document.createElement('button'); + + this.holder.className = 'track-slider'; + this.holder.style.width = window.innerWidth - 200 + 'px'; + this.holder.appendChild(this.title); + this.holder.appendChild(this.discreteHolder); + this.holder.appendChild(this.play); + this.holder.setAttribute('trackIndex', audioObject.id); + this.title.textContent = label; + this.title.className = 'track-slider-title'; + + this.discreteHolder.className = "track-slider-range"; + this.discreteHolder.style.width = window.innerWidth - 500 + 'px'; + for (var i = 0; i < interfaceScales.length; i++) { + var node = document.createElement('input'); + node.setAttribute('type', 'radio'); + node.className = 'track-radio'; node.disabled = true; - node.setAttribute('position',interfaceScales[i].position); - node.setAttribute('name',audioObject.specification.id); - node.setAttribute('id',audioObject.specification.id+'-'+String(i)); - this.discretes.push(node); - this.discreteHolder.appendChild(node); - node.onclick = function(event) - { - if (audioEngineContext.status == 0) - { - event.currentTarget.checked = false; - return; - } - var time = audioEngineContext.timer.getTestTime(); - var id = Number(event.currentTarget.parentNode.parentNode.getAttribute('trackIndex')); - var value = event.currentTarget.getAttribute('position') / 100.0; - audioEngineContext.audioObjects[id].metric.moved(time,value); - console.log('slider '+id+' moved to '+value+' ('+time+')'); - }; - } - - this.play.className = 'track-slider-button'; - this.play.textContent = "Loading..."; - this.play.value = audioObject.id; - this.play.disabled = true; - this.play.setAttribute("playstate","ready"); - this.play.onclick = function(event) - { - var id = Number(event.currentTarget.value); - //audioEngineContext.metric.sliderPlayed(id); + node.setAttribute('position', interfaceScales[i].position); + node.setAttribute('name', audioObject.specification.id); + node.setAttribute('id', audioObject.specification.id + '-' + String(i)); + this.discretes.push(node); + this.discreteHolder.appendChild(node); + node.onclick = function (event) { + if (audioEngineContext.status == 0) { + event.currentTarget.checked = false; + return; + } + var time = audioEngineContext.timer.getTestTime(); + var id = Number(event.currentTarget.parentNode.parentNode.getAttribute('trackIndex')); + var value = event.currentTarget.getAttribute('position') / 100.0; + audioEngineContext.audioObjects[id].metric.moved(time, value); + console.log('slider ' + id + ' moved to ' + value + ' (' + time + ')'); + }; + } + + this.play.className = 'track-slider-button'; + this.play.textContent = "Loading..."; + this.play.value = audioObject.id; + this.play.disabled = true; + this.play.setAttribute("playstate", "ready"); + this.play.onclick = function (event) { + var id = Number(event.currentTarget.value); + //audioEngineContext.metric.sliderPlayed(id); if (event.currentTarget.getAttribute("playstate") == "ready") audioEngineContext.play(id); else if (event.currentTarget.getAttribute("playstate") == "playing") audioEngineContext.stop(); - }; - this.resize = function(event) - { - this.holder.style.width = window.innerWidth-200 + 'px'; - this.discreteHolder.style.width = window.innerWidth-500 + 'px'; - //text.style.left = (posPix+150-($(text).width()/2)) +'px'; - for (var i=0; i<this.discretes.length; i++) - { - var width = $(this.discreteHolder).width() - 20; - var node = this.discretes[i]; - var nodeW = $(node).width(); - var position = node.getAttribute('position'); - var posPix = Math.round(width * (position / 100.0)); - node.style.left = (posPix+10 - (nodeW/2)) + 'px'; - } - }; - this.enable = function() - { - // This is used to tell the interface object that playback of this node is ready - this.play.disabled = false; - this.play.textContent = "Play"; - $(this.slider).removeClass('track-slider-disabled'); - for (var radio of this.discretes) - { + }; + this.resize = function (event) { + this.holder.style.width = window.innerWidth - 200 + 'px'; + this.discreteHolder.style.width = window.innerWidth - 500 + 'px'; + //text.style.left = (posPix+150-($(text).width()/2)) +'px'; + for (var i = 0; i < this.discretes.length; i++) { + var width = $(this.discreteHolder).width() - 20; + var node = this.discretes[i]; + var nodeW = $(node).width(); + var position = node.getAttribute('position'); + var posPix = Math.round(width * (position / 100.0)); + node.style.left = (posPix + 10 - (nodeW / 2)) + 'px'; + } + }; + this.enable = function () { + // This is used to tell the interface object that playback of this node is ready + this.play.disabled = false; + this.play.textContent = "Play"; + $(this.slider).removeClass('track-slider-disabled'); + for (var radio of this.discretes) { radio.disabled = false; } - }; - this.updateLoading = function(progress) - { - // progress is a value from 0 to 100 indicating the current download state of media files - if (progress != 100) - { + }; + this.updateLoading = function (progress) { + // progress is a value from 0 to 100 indicating the current download state of media files + if (progress != 100) { progress = String(progress); progress = progress.split('.')[0]; - this.play.textContent = progress+'%'; + this.play.textContent = progress + '%'; } else { this.play.textContent = "Play"; } - }; - - this.startPlayback = function() - { + }; + + this.startPlayback = function () { // Called by audioObject when playback begins - this.play.setAttribute("playstate","playing"); + this.play.setAttribute("playstate", "playing"); $(".track-slider").removeClass('track-slider-playing'); - $(this.holder).addClass('track-slider-playing'); - var outsideReference = document.getElementById('outside-reference'); + $(this.holder).addClass('track-slider-playing'); + var outsideReference = document.getElementById('outside-reference'); this.play.textContent = "Listening"; - if (outsideReference != null) { - $(outsideReference).removeClass('track-slider-playing'); - } + if (outsideReference != null) { + $(outsideReference).removeClass('track-slider-playing'); + } if (this.parent.specification.parent.playOne || specification.playOne) { $('.track-slider-button').text = "Wait"; - $('.track-slider-button').attr("disabled","true"); + $('.track-slider-button').attr("disabled", "true"); } } - this.stopPlayback = function() - { + this.stopPlayback = function () { // Called by audioObject when playback stops if (this.play.getAttribute("playstate") == "playing") { - this.play.setAttribute("playstate","ready"); + this.play.setAttribute("playstate", "ready"); $(this.holder).removeClass('track-slider-playing'); $('.track-slider-button').text = "Play"; this.play.textContent = "Play"; $('.track-slider-button').removeAttr("disabled"); } } - - this.getValue = function() - { - // Return the current value of the object. If there is no value, return -1 - var value = -1; - for (var i=0; i<this.discretes.length; i++) - { - if (this.discretes[i].checked == true) - { - value = this.discretes[i].getAttribute('position') / 100.0; - break; - } - } - return value; - }; - this.getPresentedId = function() - { - // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale - return this.title.textContent; - }; - this.canMove = function() - { - // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. - // These are checked primarily if the interface check option 'fragmentMoved' is enabled. - return true; - }; - this.exportXMLDOM = function(audioObject) { - // Called by the audioObject holding this element to export the interface <value> node. - // If there is no value node (such as outside reference), return null - // 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 - // Use storage.document.createElement('value'); to generate the XML node. - var node = storage.document.createElement('value'); - node.textContent = this.getValue(); - return node; - }; - this.error = function() { - // audioObject has an error!! + + this.getValue = function () { + // Return the current value of the object. If there is no value, return -1 + var value = -1; + for (var i = 0; i < this.discretes.length; i++) { + if (this.discretes[i].checked == true) { + value = this.discretes[i].getAttribute('position') / 100.0; + break; + } + } + return value; + }; + this.getPresentedId = function () { + // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale + return this.title.textContent; + }; + this.canMove = function () { + // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. + // These are checked primarily if the interface check option 'fragmentMoved' is enabled. + return true; + }; + this.exportXMLDOM = function (audioObject) { + // Called by the audioObject holding this element to export the interface <value> node. + // If there is no value node (such as outside reference), return null + // 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 + // Use storage.document.createElement('value'); to generate the XML node. + var node = storage.document.createElement('value'); + node.textContent = this.getValue(); + return node; + }; + this.error = function () { + // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } }; -function resizeWindow(event) -{ - // Called on every window resize event, use this to scale your page properly - var numObj = document.getElementsByClassName('track-slider').length; - var totalHeight = (numObj * 66)-30; - document.getElementById('scale-holder').style.width = window.innerWidth-220 + 'px'; - // Cheers edge for making me delete a canvas every resize. - var canvas = document.getElementById('scale-canvas'); +function resizeWindow(event) { + // Called on every window resize event, use this to scale your page properly + var numObj = document.getElementsByClassName('track-slider').length; + var totalHeight = (numObj * 66) - 30; + document.getElementById('scale-holder').style.width = window.innerWidth - 220 + 'px'; + // Cheers edge for making me delete a canvas every resize. + var canvas = document.getElementById('scale-canvas'); var new_canvas = document.createElement("canvas"); new_canvas.id = 'scale-canvas'; new_canvas.style.marginLeft = "150px"; canvas.parentElement.appendChild(new_canvas); canvas.parentElement.removeChild(canvas); - new_canvas.width = window.innerWidth-520; - new_canvas.height = totalHeight; - for (var i in audioEngineContext.audioObjects) - { - if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference'){ - audioEngineContext.audioObjects[i].interfaceDOM.resize(event); - } - } + new_canvas.width = window.innerWidth - 520; + new_canvas.height = totalHeight; + for (var i in audioEngineContext.audioObjects) { + if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference') { + audioEngineContext.audioObjects[i].interfaceDOM.resize(event); + } + } document.getElementById('slider-holder').style.height = totalHeight + 'px'; document.getElementById('slider').style.height = totalHeight + 70 + 'px'; - drawScale(); + drawScale(); } -function drawScale() -{ - var interfaceObj = testState.currentStateMap.interfaces[0]; - var scales = testState.currentStateMap.interfaces[0].scales; - scales = scales.sort(function(a,b) { - return a.position - b.position; - }); - var canvas = document.getElementById('scale-canvas'); - var ctx = canvas.getContext("2d"); - var height = canvas.height; - var width = canvas.width; - var textHolder = document.getElementById('scale-text-holder'); - textHolder.innerHTML = ""; - ctx.fillStyle = "#000000"; - ctx.setLineDash([1,4]); - for (var scale of scales) - { - var posPercent = scale.position / 100.0; - var posPix = Math.round(width * posPercent); - if(posPix<=0){posPix=1;} - if(posPix>=width){posPix=width-1;} - ctx.moveTo(posPix,0); - ctx.lineTo(posPix,height); - ctx.stroke(); - - var text = document.createElement('div'); - text.align = "center"; - var textC = document.createElement('span'); - textC.textContent = scale.text; - text.appendChild(textC); - text.className = "scale-text"; - textHolder.appendChild(text); - text.style.width = $(text.children[0]).width()+'px'; - text.style.left = (posPix+150-($(text).width()/2)) +'px'; - } +function drawScale() { + var interfaceObj = testState.currentStateMap.interfaces[0]; + var scales = testState.currentStateMap.interfaces[0].scales; + scales = scales.sort(function (a, b) { + return a.position - b.position; + }); + var canvas = document.getElementById('scale-canvas'); + var ctx = canvas.getContext("2d"); + var height = canvas.height; + var width = canvas.width; + var textHolder = document.getElementById('scale-text-holder'); + textHolder.innerHTML = ""; + ctx.fillStyle = "#000000"; + ctx.setLineDash([1, 4]); + for (var scale of scales) { + var posPercent = scale.position / 100.0; + var posPix = Math.round(width * posPercent); + if (posPix <= 0) { + posPix = 1; + } + if (posPix >= width) { + posPix = width - 1; + } + ctx.moveTo(posPix, 0); + ctx.lineTo(posPix, height); + ctx.stroke(); + + var text = document.createElement('div'); + text.align = "center"; + var textC = document.createElement('span'); + textC.textContent = scale.text; + text.appendChild(textC); + text.className = "scale-text"; + textHolder.appendChild(text); + text.style.width = $(text.children[0]).width() + 'px'; + text.style.left = (posPix + 150 - ($(text).width() / 2)) + 'px'; + } } function buttonSubmitClick() // TODO: Only when all songs have been played! { - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - // Check that the anchor and reference objects are correctly placed - if (interfaceContext.checkHiddenAnchor() == false) {return;} - if (interfaceContext.checkHiddenReference() == false) {return;} - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); - break; - } + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - + // Check that the anchor and reference objects are correctly placed + if (interfaceContext.checkHiddenAnchor() == false) { + return; + } + if (interfaceContext.checkHiddenReference() == false) { + return; + } + + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Warning",'You have not started the test! Please press start to begin the test!'); - return; - } - } - testState.advanceState(); - } + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Warning", 'You have not started the test! Please press start to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +}
--- a/interfaces/horizontal-sliders.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/horizontal-sliders.css Mon Nov 14 14:17:03 2016 +0000 @@ -2,137 +2,116 @@ * Hold any style information for MUSHRA interface. Customise if you like to make the interface your own! * */ + body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #ddd + /* Set the background colour (note US English spelling) to grey*/ + background-color: #ddd } - div.pageTitle { - width: auto; - height: 20px; - margin: 10px 0px; + width: auto; + height: 20px; + margin: 10px 0px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - div#slider-holder { - height: inherit; - position: absolute; - left: 0px; - z-index: 3; - margin-top:25px; + height: inherit; + position: absolute; + left: 0px; + z-index: 3; + margin-top: 25px; } - div#scale-holder { - height: inherit; - position: absolute; - left: 0px; - z-index: 2; + height: inherit; + position: absolute; + left: 0px; + z-index: 2; } - div#scale-text-holder { - position:relative; - float: left; + position: relative; + float: left; } div.scale-text { - position: absolute; - font-size: 1.2em; + position: absolute; + font-size: 1.2em; } - canvas#scale-canvas { - position: relative; - float: left; + position: relative; + float: left; } - div.track-slider { - float: left; - height: 94px; - border: solid; - border-width: 1px; - border-color: black; - padding:2px; - margin-left: 94px; - margin-bottom: 25px; + float: left; + height: 94px; + border: solid; + border-width: 1px; + border-color: black; + padding: 2px; + margin-left: 94px; + margin-bottom: 25px; } - div.track-slider-title { - float: left; - padding-top: 40px; - width: 100px; + float: left; + padding-top: 40px; + width: 100px; } - button.track-slider-button { - float: left; - width: 100px; - height: 94px; + float: left; + width: 100px; + height: 94px; } - div#outside-reference-holder { display: flex; align-content: center; justify-content: center; margin-bottom: 5px; } - button.outside-reference { position: inherit; margin: 0px 5px; } - div.track-slider-playing { - background-color: #FFDDDD; + background-color: #FFDDDD; } - input.track-slider-range { - float: left; - margin: 2px 10px; + float: left; + margin: 2px 10px; } - -input[type=range] -{ +input[type=range] { height: 94px; padding: 0px; color: rgb(255, 144, 144); } - input[type=range]::-webkit-slider-runnable-track { - cursor: pointer; - background: #fff; - border-radius: 4px; - border: 1px solid #000; + cursor: pointer; + background: #fff; + border-radius: 4px; + border: 1px solid #000; } - input[type=range]::-moz-range-track { - height: 8px; - cursor: pointer; - background: #fff; - border-radius: 4px; - border: 1px solid #000; + height: 8px; + cursor: pointer; + background: #fff; + border-radius: 4px; + border: 1px solid #000; } - input.track-slider-not-moved[type=range]::-webkit-slider-runnable-track { - background: #aaa; + background: #aaa; } - input.track-slider-not-moved[type=range]::-moz-range-track { - background: #aaa; + background: #aaa; } - div#page-count { float: left; margin: 0px 5px; } - div#master-volume-holder { position: absolute; top: 10px; left: 120px; -} \ No newline at end of file +}
--- a/interfaces/horizontal-sliders.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/horizontal-sliders.js Mon Nov 14 14:17:03 2016 +0000 @@ -2,174 +2,170 @@ loadInterface(); function loadInterface() { - // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, - // holding div's, or setting up any nodes which are present for the entire test sequence - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); - titleSpan.id="test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // 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'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + // Use this to do any one-time page / element construction. For instance, placing any stationary text objects, + // holding div's, or setting up any nodes which are present for the entire test sequence + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); + titleSpan.id = "test-title"; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // 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'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Create Submit (save) button - var submit = document.createElement("button"); - submit.innerHTML = 'Next'; - submit.onclick = buttonSubmitClick; - submit.id = 'submit-button'; - submit.style.float = 'left'; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - interfaceButtons.appendChild(submit); - + } + }; + // Create Submit (save) button + var submit = document.createElement("button"); + submit.innerHTML = 'Next'; + submit.onclick = buttonSubmitClick; + submit.id = 'submit-button'; + submit.style.float = 'left'; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + interfaceButtons.appendChild(submit); + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - // Create a slider box - var sliderBox = document.createElement('div'); - sliderBox.style.width = "100%"; - sliderBox.style.height = window.innerHeight - 200+12 + 'px'; - sliderBox.style.marginBottom = '10px'; - sliderBox.id = 'slider'; - var scaleHolder = document.createElement('div'); - scaleHolder.id = "scale-holder"; - scaleHolder.style.marginLeft = "107px"; - sliderBox.appendChild(scaleHolder); - var scaleText = document.createElement('div'); - scaleText.id = "scale-text-holder"; - scaleText.style.height = "25px"; - scaleText.style.width = "100%"; - scaleHolder.appendChild(scaleText); - var scaleCanvas = document.createElement('canvas'); - scaleCanvas.id = "scale-canvas"; - scaleCanvas.style.marginLeft = "100px"; - scaleHolder.appendChild(scaleCanvas); - var sliderObjectHolder = document.createElement('div'); - sliderObjectHolder.id = 'slider-holder'; - sliderObjectHolder.align = "center"; - sliderBox.appendChild(sliderObjectHolder); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - - testContent.style.zIndex = 1; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); + + // Create a slider box + var sliderBox = document.createElement('div'); + sliderBox.style.width = "100%"; + sliderBox.style.height = window.innerHeight - 200 + 12 + 'px'; + sliderBox.style.marginBottom = '10px'; + sliderBox.id = 'slider'; + var scaleHolder = document.createElement('div'); + scaleHolder.id = "scale-holder"; + scaleHolder.style.marginLeft = "107px"; + sliderBox.appendChild(scaleHolder); + var scaleText = document.createElement('div'); + scaleText.id = "scale-text-holder"; + scaleText.style.height = "25px"; + scaleText.style.width = "100%"; + scaleHolder.appendChild(scaleText); + var scaleCanvas = document.createElement('canvas'); + scaleCanvas.id = "scale-canvas"; + scaleCanvas.style.marginLeft = "100px"; + scaleHolder.appendChild(scaleCanvas); + var sliderObjectHolder = document.createElement('div'); + sliderObjectHolder.id = 'slider-holder'; + sliderObjectHolder.align = "center"; + sliderBox.appendChild(sliderObjectHolder); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + + testContent.style.zIndex = 1; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); testContent.appendChild(outsideRef); - testContent.appendChild(sliderBox); - testContent.appendChild(feedbackHolder); - interfaceContext.insertPoint.appendChild(testContent); + testContent.appendChild(sliderBox); + testContent.appendChild(feedbackHolder); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); }; -function loadTest(page) -{ - // Called each time a new test page is to be build. The page specification node is the only item passed in - var id = page.id; - - var feedbackHolder = document.getElementById('feedbackHolder'); +function loadTest(page) { + // Called each time a new test page is to be build. The page specification node is the only item passed in + var id = page.id; + + var feedbackHolder = document.getElementById('feedbackHolder'); feedbackHolder.innerHTML = ""; - - var interfaceObj = page.interfaces; - if (interfaceObj.length > 1) - { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - + + var interfaceObj = page.interfaces; + if (interfaceObj.length > 1) { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + // Set the page title if (typeof page.title == "string" && page.title.length > 0) { document.getElementById("test-title").textContent = page.title } - - if(interfaceObj.title != null) - { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - - // Delete outside reference - document.getElementById("outside-reference-holder").innerHTML = ""; - - var sliderBox = document.getElementById('slider-holder'); - sliderBox.innerHTML = ""; - - var commentBoxPrefix = "Comment on track"; - if (interfaceObj.commentBoxPrefix != undefined) { - commentBoxPrefix = interfaceObj.commentBoxPrefix; - } - var loopPlayback = page.loop; - - $(page.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - feedbackHolder.appendChild(node.holder); - }); - - // Find all the audioElements from the audioHolder - var index = 0; - $(page.audioElements).each(function(index,element){ - // Find URL of track - // In this jQuery loop, variable 'this' holds the current audioElement. - - var audioObject = audioEngineContext.newTrack(element); - if (element.type == 'outside-reference') - { - // Construct outside reference; - var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,document.getElementById("outside-reference-holder")); - audioObject.bindInterface(orNode); - } else { - // Create a slider per track - switch(audioObject.specification.parent.label) { + + if (interfaceObj.title != null) { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + + // Delete outside reference + document.getElementById("outside-reference-holder").innerHTML = ""; + + var sliderBox = document.getElementById('slider-holder'); + sliderBox.innerHTML = ""; + + var commentBoxPrefix = "Comment on track"; + if (interfaceObj.commentBoxPrefix != undefined) { + commentBoxPrefix = interfaceObj.commentBoxPrefix; + } + var loopPlayback = page.loop; + + $(page.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + feedbackHolder.appendChild(node.holder); + }); + + // Find all the audioElements from the audioHolder + var index = 0; + $(page.audioElements).each(function (index, element) { + // Find URL of track + // In this jQuery loop, variable 'this' holds the current audioElement. + + var audioObject = audioEngineContext.newTrack(element); + if (element.type == 'outside-reference') { + // Construct outside reference; + var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, document.getElementById("outside-reference-holder")); + audioObject.bindInterface(orNode); + } else { + // Create a slider per track + switch (audioObject.specification.parent.label) { case "none": label = ""; break; @@ -180,36 +176,32 @@ label = String.fromCharCode(65 + index); break; default: - label = ""+index; + label = "" + index; break; } - var sliderObj = new sliderObject(audioObject,label); - - if (typeof page.initialPosition === "number") - { - // Set the values - sliderObj.slider.value = page.initalPosition; - } else { - // Distribute it randomnly - sliderObj.slider.value = Math.random(); - } - sliderBox.appendChild(sliderObj.holder); - audioObject.bindInterface(sliderObj); + var sliderObj = new sliderObject(audioObject, label); + + if (typeof page.initialPosition === "number") { + // Set the values + sliderObj.slider.value = page.initalPosition; + } else { + // Distribute it randomnly + sliderObj.slider.value = Math.random(); + } + sliderBox.appendChild(sliderObj.holder); + audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - index += 1; - } - - }); + index += 1; + } + + }); var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); - for (var option of interfaceOptions) - { - if (option.type == "show") - { - switch(option.name) { + for (var option of interfaceOptions) { + if (option.type == "show") { + switch (option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.style.width = "100%"; playbackHolder.align = 'center'; @@ -219,282 +211,282 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); break; case "volume": - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": - interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); break; } } } - // Auto-align - resizeWindow(null); + // Auto-align + resizeWindow(null); } -function sliderObject(audioObject,label) -{ - // An example node, you can make this however you want for each audioElement. - // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following - // You attach them by calling audioObject.bindInterface( ) - this.parent = audioObject; - - this.holder = document.createElement('div'); - this.title = document.createElement('div'); - this.slider = document.createElement('input'); - this.play = document.createElement('button'); - - this.holder.className = 'track-slider'; - this.holder.style.width = window.innerWidth-200 + 'px'; - this.holder.appendChild(this.title); - this.holder.appendChild(this.slider); - this.holder.appendChild(this.play); - this.holder.setAttribute('trackIndex',audioObject.id); - this.title.textContent = label; - this.title.className = 'track-slider-title'; - - this.slider.type = "range"; - this.slider.className = "track-slider-range track-slider-not-moved"; - this.slider.min = "0"; - this.slider.max = "1"; - this.slider.step = "0.01"; - this.slider.style.width = window.innerWidth-420 + 'px'; - this.slider.onchange = function() - { - var time = audioEngineContext.timer.getTestTime(); - var id = Number(this.parentNode.getAttribute('trackIndex')); - audioEngineContext.audioObjects[id].metric.moved(time,this.value); - console.log('slider '+id+' moved to '+this.value+' ('+time+')'); - $(this).removeClass('track-slider-not-moved'); - }; - - this.play.className = 'track-slider-button'; - this.play.textContent = "Loading..."; - this.play.value = audioObject.id; - this.play.disabled = true; - this.play.setAttribute("playstate","ready"); - this.play.onclick = function(event) - { - var id = Number(event.currentTarget.value); - //audioEngineContext.metric.sliderPlayed(id); - if (event.currentTarget.getAttribute("playstate") == "ready") - {audioEngineContext.play(id);} - else if (event.currentTarget.getAttribute("playstate") == "playing") - {audioEngineContext.stop();} - }; - this.resize = function(event) - { - this.holder.style.width = window.innerWidth-200 + 'px'; - this.slider.style.width = window.innerWidth-420 + 'px'; - }; - this.enable = function() - { - // This is used to tell the interface object that playback of this node is ready - this.play.disabled = false; - this.play.textContent = "Play"; - $(this.slider).removeClass('track-slider-disabled'); - }; - this.updateLoading = function(progress) - { - // progress is a value from 0 to 100 indicating the current download state of media files - }; - this.startPlayback = function() - { +function sliderObject(audioObject, label) { + // An example node, you can make this however you want for each audioElement. + // However, every audioObject (audioEngineContext.audioObject) MUST have an interface object with the following + // You attach them by calling audioObject.bindInterface( ) + this.parent = audioObject; + + this.holder = document.createElement('div'); + this.title = document.createElement('div'); + this.slider = document.createElement('input'); + this.play = document.createElement('button'); + + this.holder.className = 'track-slider'; + this.holder.style.width = window.innerWidth - 200 + 'px'; + this.holder.appendChild(this.title); + this.holder.appendChild(this.slider); + this.holder.appendChild(this.play); + this.holder.setAttribute('trackIndex', audioObject.id); + this.title.textContent = label; + this.title.className = 'track-slider-title'; + + this.slider.type = "range"; + this.slider.className = "track-slider-range track-slider-not-moved"; + this.slider.min = "0"; + this.slider.max = "1"; + this.slider.step = "0.01"; + this.slider.style.width = window.innerWidth - 420 + 'px'; + this.slider.onchange = function () { + var time = audioEngineContext.timer.getTestTime(); + var id = Number(this.parentNode.getAttribute('trackIndex')); + audioEngineContext.audioObjects[id].metric.moved(time, this.value); + console.log('slider ' + id + ' moved to ' + this.value + ' (' + time + ')'); + $(this).removeClass('track-slider-not-moved'); + }; + + this.play.className = 'track-slider-button'; + this.play.textContent = "Loading..."; + this.play.value = audioObject.id; + this.play.disabled = true; + this.play.setAttribute("playstate", "ready"); + this.play.onclick = function (event) { + var id = Number(event.currentTarget.value); + //audioEngineContext.metric.sliderPlayed(id); + if (event.currentTarget.getAttribute("playstate") == "ready") { + audioEngineContext.play(id); + } else if (event.currentTarget.getAttribute("playstate") == "playing") { + audioEngineContext.stop(); + } + }; + this.resize = function (event) { + this.holder.style.width = window.innerWidth - 200 + 'px'; + this.slider.style.width = window.innerWidth - 420 + 'px'; + }; + this.enable = function () { + // This is used to tell the interface object that playback of this node is ready + this.play.disabled = false; + this.play.textContent = "Play"; + $(this.slider).removeClass('track-slider-disabled'); + }; + this.updateLoading = function (progress) { + // progress is a value from 0 to 100 indicating the current download state of media files + }; + this.startPlayback = function () { // Called when playback has begun - this.play.setAttribute("playstate","playing"); + this.play.setAttribute("playstate", "playing"); $(".track-slider").removeClass('track-slider-playing'); - $(this.holder).addClass('track-slider-playing'); - var outsideReference = document.getElementById('outside-reference'); - if (outsideReference != null) { - $(outsideReference).removeClass('track-slider-playing'); - } + $(this.holder).addClass('track-slider-playing'); + var outsideReference = document.getElementById('outside-reference'); + if (outsideReference != null) { + $(outsideReference).removeClass('track-slider-playing'); + } }; - this.stopPlayback = function() - { + this.stopPlayback = function () { // Called when playback has stopped. This gets called even if playback never started! - this.play.setAttribute("playstate","ready"); + this.play.setAttribute("playstate", "ready"); $(this.holder).removeClass('track-slider-playing'); }; - this.getValue = function() - { - // Return the current value of the object. If there is no value, return 0 - return this.slider.value; - }; - this.getPresentedId = function() - { - // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale - return this.title.textContent; - }; - this.canMove = function() - { - // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. - // These are checked primarily if the interface check option 'fragmentMoved' is enabled. - return true; - }; - this.exportXMLDOM = function(audioObject) { - // Called by the audioObject holding this element to export the interface <value> node. - // If there is no value node (such as outside reference), return null - // 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 - // Use storage.document.createElement('value'); to generate the XML node. - var node = storage.document.createElement('value'); + this.getValue = function () { + // Return the current value of the object. If there is no value, return 0 + return this.slider.value; + }; + this.getPresentedId = function () { + // Return the presented ID of the object. For instance, the APE has sliders starting from 0. Whilst AB has alphabetical scale + return this.title.textContent; + }; + this.canMove = function () { + // Return either true or false if the interface object can be moved. AB / Reference cannot, whilst sliders can and therefore have a continuous scale. + // These are checked primarily if the interface check option 'fragmentMoved' is enabled. + return true; + }; + this.exportXMLDOM = function (audioObject) { + // Called by the audioObject holding this element to export the interface <value> node. + // If there is no value node (such as outside reference), return null + // 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 + // Use storage.document.createElement('value'); to generate the XML node. + var node = storage.document.createElement('value'); node.textContent = this.slider.value; return node; - }; - this.error = function() { - // audioObject has an error!! + }; + this.error = function () { + // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } }; -function resizeWindow(event) -{ - // Called on every window resize event, use this to scale your page properly - - var numObj = document.getElementsByClassName('track-slider').length; - var totalHeight = (numObj * 125)-25; - document.getElementById('scale-holder').style.width = window.innerWidth-220 + 'px'; - // Cheers edge for making me delete a canvas every resize. - var canvas = document.getElementById('scale-canvas'); +function resizeWindow(event) { + // Called on every window resize event, use this to scale your page properly + + var numObj = document.getElementsByClassName('track-slider').length; + var totalHeight = (numObj * 125) - 25; + document.getElementById('scale-holder').style.width = window.innerWidth - 220 + 'px'; + // Cheers edge for making me delete a canvas every resize. + var canvas = document.getElementById('scale-canvas'); var new_canvas = document.createElement("canvas"); new_canvas.id = 'scale-canvas'; new_canvas.style.marginLeft = "100px"; canvas.parentElement.appendChild(new_canvas); canvas.parentElement.removeChild(canvas); - new_canvas.width = window.innerWidth-420; - new_canvas.height = totalHeight; - for (var i in audioEngineContext.audioObjects) - { - if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference'){ - audioEngineContext.audioObjects[i].interfaceDOM.resize(event); - } - } - document.getElementById("slider").style.height = totalHeight+50+'px'; - drawScale(); + new_canvas.width = window.innerWidth - 420; + new_canvas.height = totalHeight; + for (var i in audioEngineContext.audioObjects) { + if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference') { + audioEngineContext.audioObjects[i].interfaceDOM.resize(event); + } + } + document.getElementById("slider").style.height = totalHeight + 50 + 'px'; + drawScale(); } -function drawScale() -{ - var interfaceObj = testState.currentStateMap.interfaces[0]; - var scales = testState.currentStateMap.interfaces[0].scales; - scales = scales.sort(function(a,b) { - return a.position - b.position; - }); - var canvas = document.getElementById('scale-canvas'); - var ctx = canvas.getContext("2d"); - var height = canvas.height; - var width = canvas.width; - var textHolder = document.getElementById('scale-text-holder'); - textHolder.innerHTML = ""; - ctx.fillStyle = "#000000"; - ctx.setLineDash([1,4]); - for (var scale of scales) - { - var posPercent = scale.position / 100.0; - var posPix = Math.round(width * posPercent); - if(posPix<=0){posPix=1;} - if(posPix>=width){posPix=width-1;} - ctx.moveTo(posPix,0); - ctx.lineTo(posPix,height); - ctx.stroke(); - - var text = document.createElement('div'); - text.align = "center"; - var textC = document.createElement('span'); - textC.textContent = scale.text; - text.appendChild(textC); - text.className = "scale-text"; - textHolder.appendChild(text); - text.style.width = Math.ceil($(text).width())+'px'; - text.style.left = (posPix+100-($(text).width()/2)) +'px'; - } +function drawScale() { + var interfaceObj = testState.currentStateMap.interfaces[0]; + var scales = testState.currentStateMap.interfaces[0].scales; + scales = scales.sort(function (a, b) { + return a.position - b.position; + }); + var canvas = document.getElementById('scale-canvas'); + var ctx = canvas.getContext("2d"); + var height = canvas.height; + var width = canvas.width; + var textHolder = document.getElementById('scale-text-holder'); + textHolder.innerHTML = ""; + ctx.fillStyle = "#000000"; + ctx.setLineDash([1, 4]); + for (var scale of scales) { + var posPercent = scale.position / 100.0; + var posPix = Math.round(width * posPercent); + if (posPix <= 0) { + posPix = 1; + } + if (posPix >= width) { + posPix = width - 1; + } + ctx.moveTo(posPix, 0); + ctx.lineTo(posPix, height); + ctx.stroke(); + + var text = document.createElement('div'); + text.align = "center"; + var textC = document.createElement('span'); + textC.textContent = scale.text; + text.appendChild(textC); + text.className = "scale-text"; + textHolder.appendChild(text); + text.style.width = Math.ceil($(text).width()) + 'px'; + text.style.left = (posPix + 100 - ($(text).width() / 2)) + 'px'; + } } function buttonSubmitClick() // TODO: Only when all songs have been played! { - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - // Check that the anchor and reference objects are correctly placed - if (interfaceContext.checkHiddenAnchor() == false) {return;} - if (interfaceContext.checkHiddenReference() == false) {return;} - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); - break; - } + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - + // Check that the anchor and reference objects are correctly placed + if (interfaceContext.checkHiddenAnchor() == false) { + return; + } + if (interfaceContext.checkHiddenReference() == false) { + return; + } + + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Warning",'You have not started the test! Please press start to begin the test!'); - return; - } - } - testState.advanceState(); - } + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Warning", 'You have not started the test! Please press start to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); -} \ No newline at end of file +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); +}
--- a/interfaces/mushra.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/mushra.css Mon Nov 14 14:17:03 2016 +0000 @@ -2,156 +2,133 @@ * Hold any style information for MUSHRA interface. Customise if you like to make the interface your own! * */ + body { - /* Set the background colour (note US English spelling) to grey*/ - background-color: #ddd + /* Set the background colour (note US English spelling) to grey*/ + background-color: #ddd } - div.pageTitle { - width: auto; - height: 20px; - margin: 10px 0px; + width: auto; + height: 20px; + margin: 10px 0px; } - -div.pageTitle span{ - font-size: 1.5em; +div.pageTitle span { + font-size: 1.5em; } - button { - /* Specify any button structure or style */ - min-width: 20px; - background-color: #ddd + /* Specify any button structure or style */ + min-width: 20px; + background-color: #ddd } - div#slider-holder { - height: inherit; - position: absolute; - left: 0px; - z-index: 3; + height: inherit; + position: absolute; + left: 0px; + z-index: 3; } - div#scale-holder { - height: inherit; - position: absolute; - left: 0px; - z-index: 2; + height: inherit; + position: absolute; + left: 0px; + z-index: 2; } - div#scale-text-holder { - position:relative; - width: 100px; - float: left; + position: relative; + width: 100px; + float: left; } div.scale-text { - position: absolute; + position: absolute; } - canvas#scale-canvas { - position: relative; - float: left; + position: relative; + float: left; } - div.track-slider { - float: left; - width: 94px; - border: solid; - border-width: 1px; - border-color: black; - padding:2px; - margin-left: 50px; + float: left; + width: 94px; + border: solid; + border-width: 1px; + border-color: black; + padding: 2px; + margin-left: 50px; } - div#outside-reference-holder { display: flex; align-content: center; justify-content: center; margin-bottom: 5px; } - button.outside-reference { position: inherit; margin: 0px 5px; } - div.track-slider-playing { - background-color: #FFDDDD; + background-color: #FFDDDD; } - input.track-slider-range { - margin: 2px 0px; + margin: 2px 0px; } - -input[type=range][orient=vertical] -{ - writing-mode: bt-lr; /* IE */ - -webkit-appearance: slider-vertical; /* WebKit */ +input[type=range][orient=vertical] { + writing-mode: bt-lr; + /* IE */ + -webkit-appearance: slider-vertical; + /* WebKit */ width: 8px; padding: 0 5px; color: rgb(255, 144, 144); } - input[type=range]::-webkit-slider-runnable-track { - width: 8px; - cursor: pointer; - background: #fff; - border-radius: 4px; - border: 1px solid #000; + width: 8px; + cursor: pointer; + background: #fff; + border-radius: 4px; + border: 1px solid #000; } - input[type=range]::-moz-range-track { - width: 8px; - cursor: pointer; - background: #fff; - border-radius: 4px; - border: 1px solid #000; + width: 8px; + cursor: pointer; + background: #fff; + border-radius: 4px; + border: 1px solid #000; } - input[type=range]::-ms-track { - cursor: pointer; - background: #fff; - border-radius: 4px; - border: 1px solid #000; + cursor: pointer; + background: #fff; + border-radius: 4px; + border: 1px solid #000; } - input.track-slider-not-moved[type=range]::-webkit-slider-runnable-track { - background: #aaa; + background: #aaa; } - input.track-slider-not-moved[type=range]::-moz-range-track { - background: #aaa; + background: #aaa; } - - input[type=range]::-moz-range-thumb { - margin-left: -7px; - cursor: pointer; - margin-top: -1px; - box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; + margin-left: -7px; + cursor: pointer; + margin-top: -1px; + box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; } - input[type=range]::-webkit-slider-thumb { - cursor: pointer; - margin-top: -1px; - margin-left: -4px; + cursor: pointer; + margin-top: -1px; + margin-left: -4px; } - input[type=range]::-ms-thumb { - cursor: pointer; - margin-top: -1px; - margin-left: -4px; + cursor: pointer; + margin-top: -1px; + margin-left: -4px; } - input[type=range]::-ms-tooltip { - visibility:hidden; + visibility: hidden; } - div#page-count { float: left; margin: 0px 5px; } - div#master-volume-holder { position: absolute; top: 10px; left: 120px; -} \ No newline at end of file +}
--- a/interfaces/mushra.js Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/mushra.js Mon Nov 14 14:17:03 2016 +0000 @@ -7,170 +7,166 @@ loadInterface(); function loadInterface() { - // Get the dimensions of the screen available to the page - var width = window.innerWidth; - var height = window.innerHeight; - - // The injection point into the HTML page - interfaceContext.insertPoint = document.getElementById("topLevelBody"); - var testContent = document.createElement('div'); - testContent.id = 'testContent'; - - // Create the top div for the Title element - var titleAttr = specification.title; - var title = document.createElement('div'); - title.className = "title"; - title.align = "center"; - var titleSpan = document.createElement('span'); + // Get the dimensions of the screen available to the page + var width = window.innerWidth; + var height = window.innerHeight; + + // The injection point into the HTML page + interfaceContext.insertPoint = document.getElementById("topLevelBody"); + var testContent = document.createElement('div'); + testContent.id = 'testContent'; + + // Create the top div for the Title element + var titleAttr = specification.title; + var title = document.createElement('div'); + title.className = "title"; + title.align = "center"; + var titleSpan = document.createElement('span'); titleSpan.id = "test-title"; - - // Set title to that defined in XML, else set to default - if (titleAttr != undefined) { - titleSpan.textContent = titleAttr; - } else { - titleSpan.textContent = 'Listening test'; - } - // 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'; - interfaceButtons.style.height = '25px'; - - // Create playback start/stop points - var playback = document.createElement("button"); - playback.innerHTML = 'Stop'; - playback.id = 'playback-button'; - playback.style.float = 'left'; - // onclick function. Check if it is playing or not, call the correct function in the - // audioEngine, change the button text to reflect the next state. - playback.onclick = function() { - if (audioEngineContext.status == 1) { - audioEngineContext.stop(); - this.innerHTML = 'Stop'; + + // Set title to that defined in XML, else set to default + if (titleAttr != undefined) { + titleSpan.textContent = titleAttr; + } else { + titleSpan.textContent = 'Listening test'; + } + // 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'; + interfaceButtons.style.height = '25px'; + + // Create playback start/stop points + var playback = document.createElement("button"); + playback.innerHTML = 'Stop'; + playback.id = 'playback-button'; + playback.style.float = 'left'; + // onclick function. Check if it is playing or not, call the correct function in the + // audioEngine, change the button text to reflect the next state. + playback.onclick = function () { + if (audioEngineContext.status == 1) { + audioEngineContext.stop(); + this.innerHTML = 'Stop'; var time = audioEngineContext.timer.getTestTime(); console.log('Stopped at ' + time); // DEBUG/SAFETY - } - }; - // Create Submit (save) button - var submit = document.createElement("button"); - submit.innerHTML = 'Next'; - submit.onclick = buttonSubmitClick; - submit.id = 'submit-button'; - submit.style.float = 'left'; - // Append the interface buttons into the interfaceButtons object. - interfaceButtons.appendChild(playback); - interfaceButtons.appendChild(submit); - + } + }; + // Create Submit (save) button + var submit = document.createElement("button"); + submit.innerHTML = 'Next'; + submit.onclick = buttonSubmitClick; + submit.id = 'submit-button'; + submit.style.float = 'left'; + // Append the interface buttons into the interfaceButtons object. + interfaceButtons.appendChild(playback); + interfaceButtons.appendChild(submit); + // Create outside reference holder var outsideRef = document.createElement("div"); outsideRef.id = "outside-reference-holder"; - - - // Create a slider box - var sliderBox = document.createElement('div'); - sliderBox.style.width = "100%"; - sliderBox.style.height = window.innerHeight - 200+12 + 'px'; - sliderBox.style.marginBottom = '10px'; - sliderBox.id = 'slider'; - var scaleHolder = document.createElement('div'); - scaleHolder.id = "scale-holder"; - sliderBox.appendChild(scaleHolder); - var scaleText = document.createElement('div'); - scaleText.id = "scale-text-holder"; - scaleHolder.appendChild(scaleText); - var scaleCanvas = document.createElement('canvas'); - scaleCanvas.id = "scale-canvas"; - scaleHolder.appendChild(scaleCanvas); - var sliderObjectHolder = document.createElement('div'); - sliderObjectHolder.id = 'slider-holder'; - sliderObjectHolder.align = "center"; - sliderBox.appendChild(sliderObjectHolder); - - // Global parent for the comment boxes on the page - var feedbackHolder = document.createElement('div'); - feedbackHolder.id = 'feedbackHolder'; - - testContent.style.zIndex = 1; - interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema - - // Inject into HTML - testContent.appendChild(title); // Insert the title - testContent.appendChild(pagetitle); - testContent.appendChild(interfaceButtons); + + + // Create a slider box + var sliderBox = document.createElement('div'); + sliderBox.style.width = "100%"; + sliderBox.style.height = window.innerHeight - 200 + 12 + 'px'; + sliderBox.style.marginBottom = '10px'; + sliderBox.id = 'slider'; + var scaleHolder = document.createElement('div'); + scaleHolder.id = "scale-holder"; + sliderBox.appendChild(scaleHolder); + var scaleText = document.createElement('div'); + scaleText.id = "scale-text-holder"; + scaleHolder.appendChild(scaleText); + var scaleCanvas = document.createElement('canvas'); + scaleCanvas.id = "scale-canvas"; + scaleHolder.appendChild(scaleCanvas); + var sliderObjectHolder = document.createElement('div'); + sliderObjectHolder.id = 'slider-holder'; + sliderObjectHolder.align = "center"; + sliderBox.appendChild(sliderObjectHolder); + + // Global parent for the comment boxes on the page + var feedbackHolder = document.createElement('div'); + feedbackHolder.id = 'feedbackHolder'; + + testContent.style.zIndex = 1; + interfaceContext.insertPoint.innerHTML = ""; // Clear the current schema + + // Inject into HTML + testContent.appendChild(title); // Insert the title + testContent.appendChild(pagetitle); + testContent.appendChild(interfaceButtons); testContent.appendChild(outsideRef); - testContent.appendChild(sliderBox); - testContent.appendChild(feedbackHolder); - interfaceContext.insertPoint.appendChild(testContent); + testContent.appendChild(sliderBox); + testContent.appendChild(feedbackHolder); + interfaceContext.insertPoint.appendChild(testContent); - // Load the full interface - testState.initialise(); - testState.advanceState(); + // Load the full interface + testState.initialise(); + testState.advanceState(); } -function loadTest(audioHolderObject) -{ - var id = audioHolderObject.id; - - var feedbackHolder = document.getElementById('feedbackHolder'); +function loadTest(audioHolderObject) { + var id = audioHolderObject.id; + + var feedbackHolder = document.getElementById('feedbackHolder'); feedbackHolder.innerHTML = ""; - var interfaceObj = audioHolderObject.interfaces; - if (interfaceObj.length > 1) - { - console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); - } - interfaceObj = interfaceObj[0]; - + var interfaceObj = audioHolderObject.interfaces; + if (interfaceObj.length > 1) { + console.log("WARNING - This interface only supports one <interface> node per page. Using first interface node"); + } + interfaceObj = interfaceObj[0]; + // Set the page title if (typeof audioHolderObject.title == "string" && audioHolderObject.title.length > 0) { document.getElementById("test-title").textContent = audioHolderObject.title } - - if(interfaceObj.title != null) - { - document.getElementById("pageTitle").textContent = interfaceObj.title; - } - - // Delete outside reference - var outsideReferenceHolder = document.getElementById("outside-reference-holder"); + + if (interfaceObj.title != null) { + document.getElementById("pageTitle").textContent = interfaceObj.title; + } + + // Delete outside reference + var outsideReferenceHolder = document.getElementById("outside-reference-holder"); outsideReferenceHolder.innerHTML = ""; - - var sliderBox = document.getElementById('slider-holder'); - sliderBox.innerHTML = ""; - - var commentBoxPrefix = "Comment on track"; - if (interfaceObj.commentBoxPrefix != undefined) { - commentBoxPrefix = interfaceObj.commentBoxPrefix; - } - var loopPlayback = audioHolderObject.loop; - - currentTestHolder = document.createElement('audioHolder'); - currentTestHolder.id = audioHolderObject.id; - currentTestHolder.repeatCount = audioHolderObject.repeatCount; - - // Find all the audioElements from the audioHolder - var index = 0; - $(audioHolderObject.audioElements).each(function(index,element){ - // Find URL of track - // In this jQuery loop, variable 'this' holds the current audioElement. - - var audioObject = audioEngineContext.newTrack(element); - if (element.type == 'outside-reference') - { - // Construct outside reference; - var orNode = new interfaceContext.outsideReferenceDOM(audioObject,index,outsideReferenceHolder); - audioObject.bindInterface(orNode); - } else { - // Create a slider per track - switch(audioObject.specification.parent.label) { + + var sliderBox = document.getElementById('slider-holder'); + sliderBox.innerHTML = ""; + + var commentBoxPrefix = "Comment on track"; + if (interfaceObj.commentBoxPrefix != undefined) { + commentBoxPrefix = interfaceObj.commentBoxPrefix; + } + var loopPlayback = audioHolderObject.loop; + + currentTestHolder = document.createElement('audioHolder'); + currentTestHolder.id = audioHolderObject.id; + currentTestHolder.repeatCount = audioHolderObject.repeatCount; + + // Find all the audioElements from the audioHolder + var index = 0; + $(audioHolderObject.audioElements).each(function (index, element) { + // Find URL of track + // In this jQuery loop, variable 'this' holds the current audioElement. + + var audioObject = audioEngineContext.newTrack(element); + if (element.type == 'outside-reference') { + // Construct outside reference; + var orNode = new interfaceContext.outsideReferenceDOM(audioObject, index, outsideReferenceHolder); + audioObject.bindInterface(orNode); + } else { + // Create a slider per track + switch (audioObject.specification.parent.label) { case "none": label = ""; break; @@ -181,38 +177,34 @@ label = String.fromCharCode(65 + index); break; default: - label = ""+index; + label = "" + index; break; } - var sliderObj = new sliderObject(audioObject,label); - - if (typeof audioHolderObject.initialPosition === "number") - { - // Set the values - sliderObj.slider.value = audioHolderObject.initalPosition; - } else { - // Distribute it randomnly - sliderObj.slider.value = Math.random(); - } - sliderBox.appendChild(sliderObj.holder); - audioObject.bindInterface(sliderObj); + var sliderObj = new sliderObject(audioObject, label); + + if (typeof audioHolderObject.initialPosition === "number") { + // Set the values + sliderObj.slider.value = audioHolderObject.initalPosition; + } else { + // Distribute it randomnly + sliderObj.slider.value = Math.random(); + } + sliderBox.appendChild(sliderObj.holder); + audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - index += 1; - } - - }); - - + index += 1; + } + + }); + + var interfaceOptions = specification.interfaces.options.concat(interfaceObj.options); - for (var option of interfaceOptions) - { - if (option.type == "show") - { - switch(option.name) { + for (var option of interfaceOptions) { + if (option.type == "show") { + switch (option.name) { case "playhead": var playbackHolder = document.getElementById('playback-holder'); - if (playbackHolder == null) - { + if (playbackHolder == null) { playbackHolder = document.createElement('div'); playbackHolder.style.width = "100%"; playbackHolder.align = 'center'; @@ -222,308 +214,305 @@ break; case "page-count": var pagecountHolder = document.getElementById('page-count'); - if (pagecountHolder == null) - { + if (pagecountHolder == null) { pagecountHolder = document.createElement('div'); pagecountHolder.id = 'page-count'; } - pagecountHolder.innerHTML = '<span>Page '+(testState.stateIndex+1)+' of '+testState.stateMap.length+'</span>'; + pagecountHolder.innerHTML = '<span>Page ' + (testState.stateIndex + 1) + ' of ' + testState.stateMap.length + '</span>'; var inject = document.getElementById('interface-buttons'); inject.appendChild(pagecountHolder); break; case "volume": - if (document.getElementById('master-volume-holder') == null) - { + if (document.getElementById('master-volume-holder') == null) { feedbackHolder.appendChild(interfaceContext.volume.object); } break; case "comments": - interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder,true); + interfaceContext.commentBoxes.showCommentBoxes(feedbackHolder, true); break; } } } - - $(audioHolderObject.commentQuestions).each(function(index,element) { - var node = interfaceContext.createCommentQuestion(element); - feedbackHolder.appendChild(node.holder); - }); - - // Auto-align - resizeWindow(null); + + $(audioHolderObject.commentQuestions).each(function (index, element) { + var node = interfaceContext.createCommentQuestion(element); + feedbackHolder.appendChild(node.holder); + }); + + // Auto-align + resizeWindow(null); } -function sliderObject(audioObject,label) -{ - // Constructs the slider object. We use the HTML5 slider object - this.parent = audioObject; - this.holder = document.createElement('div'); - this.title = document.createElement('span'); - this.slider = document.createElement('input'); - this.play = document.createElement('button'); - - this.holder.className = 'track-slider'; - this.holder.style.height = window.innerHeight-200 + 'px'; - this.holder.appendChild(this.title); - this.holder.appendChild(this.slider); - this.holder.appendChild(this.play); - this.holder.align = "center"; - if (label == 0) - { - this.holder.style.marginLeft = '0px'; - } - this.holder.setAttribute('trackIndex',audioObject.id); - - this.title.textContent = label; - this.title.style.width = "100%"; - this.title.style.float = "left"; - - this.slider.type = "range"; - this.slider.className = "track-slider-range track-slider-not-moved"; - this.slider.min = "0"; - this.slider.max = "1"; - this.slider.step = "0.01"; - this.slider.setAttribute('orient','vertical'); - this.slider.style.height = window.innerHeight-250 + 'px'; - this.slider.onchange = function() - { - var time = audioEngineContext.timer.getTestTime(); - var id = Number(this.parentNode.getAttribute('trackIndex')); - audioEngineContext.audioObjects[id].metric.moved(time,this.value); - console.log('slider '+id+' moved to '+this.value+' ('+time+')'); - $(this).removeClass('track-slider-not-moved'); - }; - - this.play.textContent = "Loading..."; - this.play.value = audioObject.id; - this.play.style.float = "left"; - this.play.style.width = "100%"; - this.play.disabled = true; - this.play.setAttribute("playstate","ready"); - this.play.onclick = function(event) - { - var id = Number(event.currentTarget.value); - //audioEngineContext.metric.sliderPlayed(id); - if (event.currentTarget.getAttribute("playstate") == "ready") - {audioEngineContext.play(id);} - else if (event.currentTarget.getAttribute("playstate") == "playing") - {audioEngineContext.stop();} - }; - - this.enable = function() { - this.play.disabled = false; - this.play.textContent = "Play"; - $(this.slider).removeClass('track-slider-disabled'); - }; - - this.exportXMLDOM = function(audioObject) { - // Called by the audioObject holding this element. Must be present - var node = storage.document.createElement('value'); - node.textContent = this.slider.value; - return node; - }; - this.startPlayback = function() - { +function sliderObject(audioObject, label) { + // Constructs the slider object. We use the HTML5 slider object + this.parent = audioObject; + this.holder = document.createElement('div'); + this.title = document.createElement('span'); + this.slider = document.createElement('input'); + this.play = document.createElement('button'); + + this.holder.className = 'track-slider'; + this.holder.style.height = window.innerHeight - 200 + 'px'; + this.holder.appendChild(this.title); + this.holder.appendChild(this.slider); + this.holder.appendChild(this.play); + this.holder.align = "center"; + if (label == 0) { + this.holder.style.marginLeft = '0px'; + } + this.holder.setAttribute('trackIndex', audioObject.id); + + this.title.textContent = label; + this.title.style.width = "100%"; + this.title.style.float = "left"; + + this.slider.type = "range"; + this.slider.className = "track-slider-range track-slider-not-moved"; + this.slider.min = "0"; + this.slider.max = "1"; + this.slider.step = "0.01"; + this.slider.setAttribute('orient', 'vertical'); + this.slider.style.height = window.innerHeight - 250 + 'px'; + this.slider.onchange = function () { + var time = audioEngineContext.timer.getTestTime(); + var id = Number(this.parentNode.getAttribute('trackIndex')); + audioEngineContext.audioObjects[id].metric.moved(time, this.value); + console.log('slider ' + id + ' moved to ' + this.value + ' (' + time + ')'); + $(this).removeClass('track-slider-not-moved'); + }; + + this.play.textContent = "Loading..."; + this.play.value = audioObject.id; + this.play.style.float = "left"; + this.play.style.width = "100%"; + this.play.disabled = true; + this.play.setAttribute("playstate", "ready"); + this.play.onclick = function (event) { + var id = Number(event.currentTarget.value); + //audioEngineContext.metric.sliderPlayed(id); + if (event.currentTarget.getAttribute("playstate") == "ready") { + audioEngineContext.play(id); + } else if (event.currentTarget.getAttribute("playstate") == "playing") { + audioEngineContext.stop(); + } + }; + + this.enable = function () { + this.play.disabled = false; + this.play.textContent = "Play"; + $(this.slider).removeClass('track-slider-disabled'); + }; + + this.exportXMLDOM = function (audioObject) { + // Called by the audioObject holding this element. Must be present + var node = storage.document.createElement('value'); + node.textContent = this.slider.value; + return node; + }; + this.startPlayback = function () { // Called when playback has begun - this.play.setAttribute("playstate","playing"); + this.play.setAttribute("playstate", "playing"); $(".track-slider").removeClass('track-slider-playing'); - $(this.holder).addClass('track-slider-playing'); - var outsideReference = document.getElementById('outside-reference'); - if (outsideReference != null) { - $(outsideReference).removeClass('track-slider-playing'); - } + $(this.holder).addClass('track-slider-playing'); + var outsideReference = document.getElementById('outside-reference'); + if (outsideReference != null) { + $(outsideReference).removeClass('track-slider-playing'); + } this.play.textContent = "Stop"; }; - this.stopPlayback = function() - { + this.stopPlayback = function () { // Called when playback has stopped. This gets called even if playback never started! - this.play.setAttribute("playstate","ready"); + this.play.setAttribute("playstate", "ready"); $(this.holder).removeClass('track-slider-playing'); this.play.textContent = "Play"; }; - this.getValue = function() { - return this.slider.value; - }; - - this.resize = function(event) - { - this.holder.style.height = window.innerHeight-200 + 'px'; - this.slider.style.height = window.innerHeight-250 + 'px'; - }; - this.updateLoading = function(progress) - { - progress = String(progress); - progress = progress.substr(0,5); - this.play.textContent = "Loading: "+progress+"%"; - }; - - if (this.parent.state == 1) - { - this.enable(); - } - this.getPresentedId = function() - { - return this.title.textContent; - }; - this.canMove = function() - { - return true; - }; - this.error = function() { - // audioObject has an error!! + this.getValue = function () { + return this.slider.value; + }; + + this.resize = function (event) { + this.holder.style.height = window.innerHeight - 200 + 'px'; + this.slider.style.height = window.innerHeight - 250 + 'px'; + }; + this.updateLoading = function (progress) { + progress = String(progress); + progress = progress.substr(0, 5); + this.play.textContent = "Loading: " + progress + "%"; + }; + + if (this.parent.state == 1) { + this.enable(); + } + this.getPresentedId = function () { + return this.title.textContent; + }; + this.canMove = function () { + return true; + }; + this.error = function () { + // audioObject has an error!! this.playback.textContent = "Error"; $(this.playback).addClass("error-colour"); } } -function resizeWindow(event) -{ - // Function called when the window has been resized. - // MANDATORY FUNCTION - - var outsideRef = document.getElementById('outside-reference'); - if(outsideRef != null) - { - outsideRef.style.left = (window.innerWidth-120)/2 + 'px'; - } - - // Auto-align - var numObj = document.getElementsByClassName('track-slider').length; - var totalWidth = (numObj-1)*150+100; - var diff = (window.innerWidth - totalWidth)/2; - document.getElementById('slider').style.height = window.innerHeight - 180 + 'px'; - if (diff <= 0){diff = 0;} - document.getElementById('slider-holder').style.marginLeft = diff + 'px'; - for (var i in audioEngineContext.audioObjects) - { - if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference'){ - audioEngineContext.audioObjects[i].interfaceDOM.resize(event); - } - } - document.getElementById('scale-holder').style.marginLeft = (diff-100) + 'px'; - document.getElementById('scale-text-holder').style.height = window.innerHeight-194 + 'px'; +function resizeWindow(event) { + // Function called when the window has been resized. + // MANDATORY FUNCTION + + var outsideRef = document.getElementById('outside-reference'); + if (outsideRef != null) { + outsideRef.style.left = (window.innerWidth - 120) / 2 + 'px'; + } + + // Auto-align + var numObj = document.getElementsByClassName('track-slider').length; + var totalWidth = (numObj - 1) * 150 + 100; + var diff = (window.innerWidth - totalWidth) / 2; + document.getElementById('slider').style.height = window.innerHeight - 180 + 'px'; + if (diff <= 0) { + diff = 0; + } + document.getElementById('slider-holder').style.marginLeft = diff + 'px'; + for (var i in audioEngineContext.audioObjects) { + if (audioEngineContext.audioObjects[i].specification.type != 'outside-reference') { + audioEngineContext.audioObjects[i].interfaceDOM.resize(event); + } + } + document.getElementById('scale-holder').style.marginLeft = (diff - 100) + 'px'; + document.getElementById('scale-text-holder').style.height = window.innerHeight - 194 + 'px'; // Cheers edge for making me delete a canvas every resize. - var canvas = document.getElementById('scale-canvas'); + var canvas = document.getElementById('scale-canvas'); var new_canvas = document.createElement("canvas"); new_canvas.id = 'scale-canvas'; canvas.parentElement.appendChild(new_canvas); canvas.parentElement.removeChild(canvas); - new_canvas.width = totalWidth; - new_canvas.height = window.innerHeight-194; - drawScale(); + new_canvas.width = totalWidth; + new_canvas.height = window.innerHeight - 194; + drawScale(); } -function drawScale() -{ - var interfaceObj = testState.currentStateMap.interfaces[0]; - var scales = testState.currentStateMap.interfaces[0].scales; - scales = scales.sort(function(a,b) { - return a.position - b.position; - }); - var canvas = document.getElementById('scale-canvas'); - var ctx = canvas.getContext("2d"); - var height = canvas.height; - var width = canvas.width; - ctx.clearRect(0,0,canvas.width,canvas.height); - var draw_heights = [24, height-34]; - var textHolder = document.getElementById('scale-text-holder'); - textHolder.innerHTML = ""; - var lastHeight = 0; - for (var scale of scales) - { - var posPercent = scale.position / 100.0; - var posPix = (1-posPercent)*(draw_heights[1]-draw_heights[0])+draw_heights[0]; - ctx.fillStyle = "#000000"; - ctx.setLineDash([1,2]); - ctx.moveTo(0,posPix); - ctx.lineTo(width,posPix); - ctx.stroke(); - var text = document.createElement('div'); - text.align = "right"; - var textC = document.createElement('span'); - textC.textContent = scale.text; - text.appendChild(textC); - text.className = "scale-text"; - textHolder.appendChild(text); - text.style.top = (posPix-9) + 'px'; - text.style.left = 100 - ($(text).width()+3) + 'px'; - lastHeight = posPix; - } +function drawScale() { + var interfaceObj = testState.currentStateMap.interfaces[0]; + var scales = testState.currentStateMap.interfaces[0].scales; + scales = scales.sort(function (a, b) { + return a.position - b.position; + }); + var canvas = document.getElementById('scale-canvas'); + var ctx = canvas.getContext("2d"); + var height = canvas.height; + var width = canvas.width; + ctx.clearRect(0, 0, canvas.width, canvas.height); + var draw_heights = [24, height - 34]; + var textHolder = document.getElementById('scale-text-holder'); + textHolder.innerHTML = ""; + var lastHeight = 0; + for (var scale of scales) { + var posPercent = scale.position / 100.0; + var posPix = (1 - posPercent) * (draw_heights[1] - draw_heights[0]) + draw_heights[0]; + ctx.fillStyle = "#000000"; + ctx.setLineDash([1, 2]); + ctx.moveTo(0, posPix); + ctx.lineTo(width, posPix); + ctx.stroke(); + var text = document.createElement('div'); + text.align = "right"; + var textC = document.createElement('span'); + textC.textContent = scale.text; + text.appendChild(textC); + text.className = "scale-text"; + textHolder.appendChild(text); + text.style.top = (posPix - 9) + 'px'; + text.style.left = 100 - ($(text).width() + 3) + 'px'; + lastHeight = posPix; + } } function buttonSubmitClick() // TODO: Only when all songs have been played! { - var checks = []; - checks = checks.concat(testState.currentStateMap.interfaces[0].options); - checks = checks.concat(specification.interfaces.options); - var canContinue = true; - - // Check that the anchor and reference objects are correctly placed - if (interfaceContext.checkHiddenAnchor() == false) {return;} - if (interfaceContext.checkHiddenReference() == false) {return;} - - for (var i=0; i<checks.length; i++) { - if (checks[i].type == 'check') - { - switch(checks[i].name) { - case 'fragmentPlayed': - // Check if all fragments have been played - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentFullPlayback': - // Check all fragments have been played to their full length - var checkState = interfaceContext.checkAllPlayed(); - if (checkState == false) {canContinue = false;} - console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); - break; - case 'fragmentMoved': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllMoved(); - if (checkState == false) {canContinue = false;} - break; - case 'fragmentComments': - // Check all fragment sliders have been moved. - var checkState = interfaceContext.checkAllCommented(); - if (checkState == false) {canContinue = false;} - break; - case 'scalerange': - // Check the scale has been used effectively - var checkState = interfaceContext.checkScaleRange(checks[i].min,checks[i].max); - if (checkState == false) {canContinue = false;} - break; - default: - console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface"); - break; - } + var checks = []; + checks = checks.concat(testState.currentStateMap.interfaces[0].options); + checks = checks.concat(specification.interfaces.options); + var canContinue = true; - } - if (!canContinue) {break;} - } - + // Check that the anchor and reference objects are correctly placed + if (interfaceContext.checkHiddenAnchor() == false) { + return; + } + if (interfaceContext.checkHiddenReference() == false) { + return; + } + + for (var i = 0; i < checks.length; i++) { + if (checks[i].type == 'check') { + switch (checks[i].name) { + case 'fragmentPlayed': + // Check if all fragments have been played + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentFullPlayback': + // Check all fragments have been played to their full length + var checkState = interfaceContext.checkAllPlayed(); + if (checkState == false) { + canContinue = false; + } + console.log('NOTE: fragmentFullPlayback not currently implemented, performing check fragmentPlayed instead'); + break; + case 'fragmentMoved': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllMoved(); + if (checkState == false) { + canContinue = false; + } + break; + case 'fragmentComments': + // Check all fragment sliders have been moved. + var checkState = interfaceContext.checkAllCommented(); + if (checkState == false) { + canContinue = false; + } + break; + case 'scalerange': + // Check the scale has been used effectively + var checkState = interfaceContext.checkScaleRange(checks[i].min, checks[i].max); + if (checkState == false) { + canContinue = false; + } + break; + default: + console.log("WARNING - Check option " + checks[i].check + " is not supported on this interface"); + break; + } + + } + if (!canContinue) { + break; + } + } + if (canContinue) { - if (audioEngineContext.status == 1) { - var playback = document.getElementById('playback-button'); - playback.click(); - // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options - } else - { - if (audioEngineContext.timer.testStarted == false) - { - interfaceContext.lightbox.post("Message",'You have not started the test! Please press start to begin the test!'); - return; - } - } - testState.advanceState(); - } + if (audioEngineContext.status == 1) { + var playback = document.getElementById('playback-button'); + playback.click(); + // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options + } else { + if (audioEngineContext.timer.testStarted == false) { + interfaceContext.lightbox.post("Message", 'You have not started the test! Please press start to begin the test!'); + return; + } + } + testState.advanceState(); + } } -function pageXMLSave(store, pageSpecification) -{ - // MANDATORY - // Saves a specific test page - // You can use this space to add any extra nodes to your XML <audioHolder> saves - // Get the current <page> information in store (remember to appendChild your data to it) - // pageSpecification is the current page node configuration - // To create new XML nodes, use storage.document.createElement(); +function pageXMLSave(store, pageSpecification) { + // MANDATORY + // Saves a specific test page + // You can use this space to add any extra nodes to your XML <audioHolder> saves + // Get the current <page> information in store (remember to appendChild your data to it) + // pageSpecification is the current page node configuration + // To create new XML nodes, use storage.document.createElement(); }
--- a/interfaces/timeline.css Mon Nov 14 12:11:38 2016 +0000 +++ b/interfaces/timeline.css Mon Nov 14 14:17:03 2016 +0000 @@ -2,7 +2,6 @@ display: flex; justify-content: center; } - div.timeline-element-content { max-width: 800px; min-width: 200px; @@ -10,15 +9,13 @@ margin: 10px 0px; padding: 20px; } - div.timeline-element-canvas-holder { display: flex; width: inherit; height: 160px; margin-left: 50px; } - -canvas.canvas-layer1{ +canvas.canvas-layer1 { position: absolute; } canvas.canvas-layer2 { @@ -33,21 +30,17 @@ position: absolute; z-index: -3; } - canvas.timeline-element-canvas { border: 1px solid black; } - canvas.canvas-disabled { background-color: gray; } - div.timeline-element-comment-holder { display: flex; flex-wrap: wrap; justify-content: space-between; } - div.comment-entry { border: 1px solid #444444; max-width: 600px; @@ -59,13 +52,11 @@ display: flex; flex-direction: column; } - div.comment-entry-header { display: flex; justify-content: space-between; } - textarea.comment-entry-text { resize: none; margin: auto; -} \ No newline at end of file +}
--- a/js/WAVE.js Mon Nov 14 12:11:38 2016 +0000 +++ b/js/WAVE.js Mon Nov 14 14:17:03 2016 +0000 @@ -1,131 +1,120 @@ // Decode and perform WAVE file byte level manipulation -find_subarray = function(arr,subarr) { +find_subarray = function (arr, subarr) { var arr_length = arr.length; var subarr_length = subarr.length; var last_check_index = arr_length - subarr_length; - + positionLoop: - for (var i=0; i <= last_check_index; i++) - { - for (var j=0; j< subarr_length; j++) - { - if (arr[i + j] !== subarr[j]) { - continue positionLoop; + for (var i = 0; i <= last_check_index; i++) { + for (var j = 0; j < subarr_length; j++) { + if (arr[i + j] !== subarr[j]) { + continue positionLoop; + } } + return i; } - return i; - } return -1; }; function convertToInteger(arr) { var value = 0; - for (var i=0; i<arr.length; i++) - { - value += arr[i]<<(i*8); + for (var i = 0; i < arr.length; i++) { + value += arr[i] << (i * 8); } return value; } + function convertToString(arr) { var str = ""; - for (var i=0; i<arr.length; i++) - { + for (var i = 0; i < arr.length; i++) { str = str.concat(String.fromCharCode(arr[i])); } return str; } -function WAVE() -{ +function WAVE() { // The WAVE file object this.status == 'WAVE_DECLARED' - + this.decoded_data = null; - + this.RIFF = String(); //ChunkID - this.size; //ChunkSize - this.FT_Header; //Format - this.fmt_marker; //Subchunk1ID - this.formatDataLength; //Subchunk1Size - this.type; //AudioFormat - this.num_channels; //NumChannels - this.sample_rate; //SampleRate - this.byte_rate; //ByteRate - this.block_align; //BlockAlign - this.bits_per_sample; //BitsPerSample - this.data_header; //Subchunk2ID - this.data_size; //Subchunk2Size + this.size; //ChunkSize + this.FT_Header; //Format + this.fmt_marker; //Subchunk1ID + this.formatDataLength; //Subchunk1Size + this.type; //AudioFormat + this.num_channels; //NumChannels + this.sample_rate; //SampleRate + this.byte_rate; //ByteRate + this.block_align; //BlockAlign + this.bits_per_sample; //BitsPerSample + this.data_header; //Subchunk2ID + this.data_size; //Subchunk2Size this.num_samples; - - this.open = function(IOArrayBuffer) - { + + this.open = function (IOArrayBuffer) { var IOView8 = new Uint8Array(IOArrayBuffer); - this.RIFF = convertToString(IOView8.subarray(0,4)); - if (this.RIFF != 'RIFF') - { + this.RIFF = convertToString(IOView8.subarray(0, 4)); + if (this.RIFF != 'RIFF') { console.log('WAVE ERR - Not a RIFF file'); return 1; } - this.size = convertToInteger(IOView8.subarray(4,8)); - this.FT_Header = convertToString(IOView8.subarray(8,12)); - this.fmt_marker = convertToString(IOView8.subarray(12,16)); - this.formatDataLength = convertToInteger(IOView8.subarray(16,20)); - this.type = convertToInteger(IOView8.subarray(20,22)); - this.num_channels = convertToInteger(IOView8.subarray(22,24)); - this.sample_rate = convertToInteger(IOView8.subarray(24,28)); - this.byte_rate = convertToInteger(IOView8.subarray(28,32)); - this.block_align = convertToInteger(IOView8.subarray(32,34)); - this.bits_per_sample = convertToInteger(IOView8.subarray(34,36)); - + this.size = convertToInteger(IOView8.subarray(4, 8)); + this.FT_Header = convertToString(IOView8.subarray(8, 12)); + this.fmt_marker = convertToString(IOView8.subarray(12, 16)); + this.formatDataLength = convertToInteger(IOView8.subarray(16, 20)); + this.type = convertToInteger(IOView8.subarray(20, 22)); + this.num_channels = convertToInteger(IOView8.subarray(22, 24)); + this.sample_rate = convertToInteger(IOView8.subarray(24, 28)); + this.byte_rate = convertToInteger(IOView8.subarray(28, 32)); + this.block_align = convertToInteger(IOView8.subarray(32, 34)); + this.bits_per_sample = convertToInteger(IOView8.subarray(34, 36)); + // Find the data header first - var data_start = find_subarray(IOView8,[100, 97, 116, 97]); - - this.data_header = convertToString(IOView8.subarray(data_start,data_start+4)); - this.data_size = convertToInteger(IOView8.subarray(data_start+4,data_start+8)); - + var data_start = find_subarray(IOView8, [100, 97, 116, 97]); + + this.data_header = convertToString(IOView8.subarray(data_start, data_start + 4)); + this.data_size = convertToInteger(IOView8.subarray(data_start + 4, data_start + 8)); + this.num_samples = this.data_size / this.block_align; - + this.decoded_data = []; if (this.type != 1 && this.type != 3) { console.log("Neither PCM nor IEEE float, cannot decode"); return 1; } - for (var c=0; c<this.num_channels; c++) - { + for (var c = 0; c < this.num_channels; c++) { this.decoded_data.push(new Float32Array(this.num_samples)); } - var sampleDataOffset = data_start+8; - + var sampleDataOffset = data_start + 8; + // Now need to decode the data from sampleDataOffset // Data is always interleved var data_view; - if (this.type == 3) - { + if (this.type == 3) { // Already in float if (this.bits_per_sample == 32) { - data_view = new Float32Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size)); + data_view = new Float32Array(IOArrayBuffer.slice(sampleDataOffset, sampleDataOffset + this.data_size)); } else if (this.bits_per_sample == 64) { - data_view = new Float64Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size)); + data_view = new Float64Array(IOArrayBuffer.slice(sampleDataOffset, sampleDataOffset + this.data_size)); } - } else if (this.type == 1) - { - data_view = new Float32Array(this.num_samples*this.num_channels); - integerConvert(new Uint8Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size)),data_view,this.bits_per_sample/8); + } else if (this.type == 1) { + data_view = new Float32Array(this.num_samples * this.num_channels); + integerConvert(new Uint8Array(IOArrayBuffer.slice(sampleDataOffset, sampleDataOffset + this.data_size)), data_view, this.bits_per_sample / 8); } - deInterlace(data_view,this.decoded_data); + deInterlace(data_view, this.decoded_data); return 0; }; } -function deInterlace(src_array, dst_array) -{ +function deInterlace(src_array, dst_array) { var number = src_array.length; var channels = dst_array.length; var channel_index = 0; var dst_index = 0; - for (var n=0; n<number; n++) - { + for (var n = 0; n < number; n++) { dst_array[channel_index][dst_index] = src_array[n]; channel_index++; if (channel_index >= channels) { @@ -135,21 +124,18 @@ } } -function integerConvert(srcView,dstView,srcBytes) -{ +function integerConvert(srcView, dstView, srcBytes) { //Convert integers of a Uint8Array of certain byte length into a Float32Array var number = dstView.length; - var outBits = srcBytes*8; + var outBits = srcBytes * 8; var endShift = 32 - outBits; - if (srcView.length != dstView.length*srcBytes) - { + if (srcView.length != dstView.length * srcBytes) { return -1; } - for (var n=0; n<number; n++) - { - var srcIndex = n*srcBytes; - var intData = convertToInteger(srcView.subarray(srcIndex,srcIndex+srcBytes)); + for (var n = 0; n < number; n++) { + var srcIndex = n * srcBytes; + var intData = convertToInteger(srcView.subarray(srcIndex, srcIndex + srcBytes)); intData = (intData << (endShift)); dstView[n] = intData / 2147483648; } -} \ No newline at end of file +}
--- a/js/loader.js Mon Nov 14 12:11:38 2016 +0000 +++ b/js/loader.js Mon Nov 14 14:17:03 2016 +0000 @@ -1,6 +1,6 @@ // Script to load the relevant JS files if the system supports it -window.onload = function() { +window.onload = function () { // First check if the Web Audio API is supported if (window.AudioContext == undefined && window.webkitAudioContext == undefined) { // Display unsuported error message @@ -16,7 +16,7 @@ } else { var head = document.getElementsByTagName("head")[0]; var src_list = ['js/specification.js', 'js/core.js', 'js/loudness.js', 'js/xmllint.js', 'js/WAVE.js']; - for (var i=0; i<src_list.length; i++) { + for (var i = 0; i < src_list.length; i++) { var src = src_list[i]; var script = document.createElement("script"); script.type = "text/javascript"; @@ -26,4 +26,4 @@ head.appendChild(script); } } -} \ No newline at end of file +}
--- a/js/loudness.js Mon Nov 14 12:11:38 2016 +0000 +++ b/js/loudness.js Mon Nov 14 14:17:03 2016 +0000 @@ -8,98 +8,88 @@ var interval_cal_loudness_event = null; -if (typeof OfflineAudioContext == "undefined"){ - var OfflineAudioContext = webkitOfflineAudioContext; +if (typeof OfflineAudioContext == "undefined") { + var OfflineAudioContext = webkitOfflineAudioContext; } -function calculateLoudness(buffer, timescale, target, offlineContext) -{ - // This function returns the EBU R 128 specification loudness model and sets the linear gain required to match -23 LUFS - // buffer -> Web Audio API Buffer object - // timescale -> M or Momentary (returns Array), S or Short (returns Array), - // I or Integrated (default, returns number) - // target -> default is -23 LUFS but can be any LUFS measurement. - if(navigator.platform == 'iPad' || navigator.platform == 'iPhone') { +function calculateLoudness(buffer, timescale, target, offlineContext) { + // This function returns the EBU R 128 specification loudness model and sets the linear gain required to match -23 LUFS + // buffer -> Web Audio API Buffer object + // timescale -> M or Momentary (returns Array), S or Short (returns Array), + // I or Integrated (default, returns number) + // target -> default is -23 LUFS but can be any LUFS measurement. + if (navigator.platform == 'iPad' || navigator.platform == 'iPhone') { buffer.ready(); } - if (buffer == undefined) - { - return 0; - } - if (timescale == undefined) - { - timescale = "I"; - } - if (target == undefined) - { - target = -23; - } - if (offlineContext == undefined) - { - offlineContext = new OfflineAudioContext(audioContext.destination.channelCount, buffer.buffer.duration*audioContext.sampleRate, audioContext.sampleRate); - } - // Create the required filters - var KFilter = offlineContext.createBiquadFilter(); - KFilter.type = "highshelf"; - KFilter.gain.value = 4; - KFilter.frequency.value = 1500; - - var HPFilter = offlineContext.createBiquadFilter(); - HPFilter.type = "highpass"; - HPFilter.Q.value = 0.5; - HPFilter.frequency.value = 38; - // copy Data into the process buffer - var processSource = offlineContext.createBufferSource(); - processSource.buffer = buffer.buffer; - - processSource.connect(KFilter); - KFilter.connect(HPFilter); - HPFilter.connect(offlineContext.destination); - offlineContext.oncomplete = function(renderedBuffer) { - // Have the renderedBuffer information, now continue processing - if (typeof renderedBuffer.renderedBuffer == 'object') { - renderedBuffer = renderedBuffer.renderedBuffer; - } - switch(timescale) - { - case "I": - // Calculate the Mean Squared of a signal - var MS = calculateMeanSquared(renderedBuffer,0.4,0.75); - // Calculate the Loudness of each block - var MSL = calculateLoudnessFromBlocks(MS); - // Get blocks from Absolute Gate - var LK = loudnessGate(MSL,MS,-70); - // Calculate Loudness - var LK_gate = loudnessOfBlocks(LK); - // Get blocks from Relative Gate - var RK = loudnessGate(MSL,MS,LK_gate-10); - var RK_gate = loudnessOfBlocks(RK); - buffer.buffer.lufs = RK_gate; - } + if (buffer == undefined) { + return 0; + } + if (timescale == undefined) { + timescale = "I"; + } + if (target == undefined) { + target = -23; + } + if (offlineContext == undefined) { + offlineContext = new OfflineAudioContext(audioContext.destination.channelCount, buffer.buffer.duration * audioContext.sampleRate, audioContext.sampleRate); + } + // Create the required filters + var KFilter = offlineContext.createBiquadFilter(); + KFilter.type = "highshelf"; + KFilter.gain.value = 4; + KFilter.frequency.value = 1500; + + var HPFilter = offlineContext.createBiquadFilter(); + HPFilter.type = "highpass"; + HPFilter.Q.value = 0.5; + HPFilter.frequency.value = 38; + // copy Data into the process buffer + var processSource = offlineContext.createBufferSource(); + processSource.buffer = buffer.buffer; + + processSource.connect(KFilter); + KFilter.connect(HPFilter); + HPFilter.connect(offlineContext.destination); + offlineContext.oncomplete = function (renderedBuffer) { + // Have the renderedBuffer information, now continue processing + if (typeof renderedBuffer.renderedBuffer == 'object') { + renderedBuffer = renderedBuffer.renderedBuffer; + } + switch (timescale) { + case "I": + // Calculate the Mean Squared of a signal + var MS = calculateMeanSquared(renderedBuffer, 0.4, 0.75); + // Calculate the Loudness of each block + var MSL = calculateLoudnessFromBlocks(MS); + // Get blocks from Absolute Gate + var LK = loudnessGate(MSL, MS, -70); + // Calculate Loudness + var LK_gate = loudnessOfBlocks(LK); + // Get blocks from Relative Gate + var RK = loudnessGate(MSL, MS, LK_gate - 10); + var RK_gate = loudnessOfBlocks(RK); + buffer.buffer.lufs = RK_gate; + } buffer.ready(); - }; + }; processSource.start(0); - offlineContext.startRendering(); + offlineContext.startRendering(); } -function calculateMeanSquared(buffer,frame_dur,frame_overlap) -{ - frame_size = Math.floor(buffer.sampleRate*frame_dur); - step_size = Math.floor(frame_size*(1.0-frame_overlap)); - num_frames = Math.floor((buffer.length-frame_size)/step_size); - +function calculateMeanSquared(buffer, frame_dur, frame_overlap) { + frame_size = Math.floor(buffer.sampleRate * frame_dur); + step_size = Math.floor(frame_size * (1.0 - frame_overlap)); + num_frames = Math.floor((buffer.length - frame_size) / step_size); + MS = Array(buffer.numberOfChannels); - for (var c=0; c<buffer.numberOfChannels; c++) - { + for (var c = 0; c < buffer.numberOfChannels; c++) { MS[c] = new Float32Array(num_frames); var data = buffer.getChannelData(c); - for (var no=0; no<num_frames; no++) - { + for (var no = 0; no < num_frames; no++) { MS[c][no] = 0.0; - for (var ptr=0; ptr<frame_size; ptr++) - { - var sample = data[no*step_size+ptr]; - MS[c][no] += sample*sample; + for (var ptr = 0; ptr < frame_size; ptr++) { + var sample = data[no * step_size + ptr]; + MS[c][no] += sample * sample; } MS[c][no] /= frame_size; } @@ -107,41 +97,35 @@ return MS; } -function calculateLoudnessFromBlocks(blocks) -{ +function calculateLoudnessFromBlocks(blocks) { var num_frames = blocks[0].length; var num_channels = blocks.length; var MSL = Array(num_frames); - for (var n=0; n<num_frames; n++) - { + for (var n = 0; n < num_frames; n++) { var sum = 0; - for (var c=0; c<num_channels; c++) - { + for (var c = 0; c < num_channels; c++) { var G = 1.0; - if(G >= 3){G = 1.41;} - sum += blocks[c][n]*G; + if (G >= 3) { + G = 1.41; + } + sum += blocks[c][n] * G; } - MSL[n] = -0.691 + 10*Math.log10(sum); + MSL[n] = -0.691 + 10 * Math.log10(sum); } return MSL; } -function loudnessGate(blocks,source,threshold) -{ +function loudnessGate(blocks, source, threshold) { var num_frames = source[0].length; var num_channels = source.length; var LK = Array(num_channels); - for (var c=0; c<num_channels; c++) - { + for (var c = 0; c < num_channels; c++) { LK[c] = []; } - - for (var n=0; n<num_frames; n++) - { - if (blocks[n] > threshold) - { - for (var c=0; c<num_channels; c++) - { + + for (var n = 0; n < num_frames; n++) { + if (blocks[n] > threshold) { + for (var c = 0; c < num_channels; c++) { LK[c].push(source[c][n]); } } @@ -149,23 +133,22 @@ return LK; } -function loudnessOfBlocks(blocks) -{ +function loudnessOfBlocks(blocks) { var num_frames = blocks[0].length; var num_channels = blocks.length; var loudness = 0.0; - for (var n=0; n<num_frames; n++) - { + for (var n = 0; n < num_frames; n++) { var sum = 0; - for (var c=0; c<num_channels; c++) - { + for (var c = 0; c < num_channels; c++) { var G = 1.0; - if(G >= 3){G = 1.41;} - sum += blocks[c][n]*G; + if (G >= 3) { + G = 1.41; + } + sum += blocks[c][n] * G; } sum /= num_frames; loudness += sum; } loudness = -0.691 + 10 * Math.log10(loudness); return loudness; -} \ No newline at end of file +}
--- a/js/specification.js Mon Nov 14 12:11:38 2016 +0000 +++ b/js/specification.js Mon Nov 14 14:17:03 2016 +0000 @@ -1,12 +1,12 @@ function Specification() { - // Handles the decoding of the project specification XML into a simple JavaScript Object. - + // Handles the decoding of the project specification XML into a simple JavaScript Object. + // <setup> attributes - this.interface = null; - this.projectReturn = null; + this.interface = null; + this.projectReturn = null; this.returnURL = null; - this.randomiseOrder = null; - this.poolSize = null; + this.randomiseOrder = null; + this.poolSize = null; this.loudness = null; this.sampleRate = null; this.calibration = null; @@ -14,32 +14,31 @@ this.preSilence = null; this.postSilence = null; this.playOne = null; - + // nodes this.metrics = null; this.preTest = undefined; this.postTest = undefined; - this.pages = []; - this.interfaces = null; - this.errors = []; - this.schema = null; + this.pages = []; + this.interfaces = null; + this.errors = []; + this.schema = null; this.exitText = "Thank you."; - - this.processAttribute = function(attribute,schema,schemaRoot) - { - // attribute is the string returned from getAttribute on the XML - // schema is the <xs:attribute> node - if (schema.getAttribute('name') == undefined && schema.getAttribute('ref') != undefined) - { - schema = schemaRoot.getAllElementsByName(schema.getAttribute('ref'))[0]; - } - var defaultOpt = schema.getAttribute('default'); - if (attribute == null) { - attribute = defaultOpt; - } - var dataType = schema.getAttribute('type'); - if (typeof dataType == "string") { dataType = dataType.substr(3);} - else { + + this.processAttribute = function (attribute, schema, schemaRoot) { + // attribute is the string returned from getAttribute on the XML + // schema is the <xs:attribute> node + if (schema.getAttribute('name') == undefined && schema.getAttribute('ref') != undefined) { + schema = schemaRoot.getAllElementsByName(schema.getAttribute('ref'))[0]; + } + var defaultOpt = schema.getAttribute('default'); + if (attribute == null) { + attribute = defaultOpt; + } + var dataType = schema.getAttribute('type'); + if (typeof dataType == "string") { + dataType = dataType.substr(3); + } else { var rest = schema.getAllElementsByTagName("xs:restriction").concat(schema.getAllElementsByTagName("xs:enumeration")); if (rest.length > 0) { dataType = rest[0].getAttribute("base"); @@ -52,129 +51,122 @@ dataType = "string"; } } - if (attribute == null) - { - return attribute; - } - switch(dataType) - { - case "boolean": - if (attribute == 'true'){attribute = true;}else{attribute=false;} - break; - case "negativeInteger": - case "positiveInteger": - case "nonNegativeInteger": - case "nonPositiveInteger": - case "integer": - case "decimal": - case "short": - attribute = Number(attribute); - break; - case "string": - default: - attribute = String(attribute); - break; - } - return attribute; - }; - - this.decode = function(projectXML) { - this.errors = []; - // projectXML - DOM Parsed document - this.projectXML = projectXML.childNodes[0]; - var setupNode = projectXML.getElementsByTagName('setup')[0]; - var schemaSetup = this.schema.getAllElementsByName('setup')[0]; - // First decode the attributes - var attributes = schemaSetup.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributes.length; i++) - { - var attributeName = attributes[i].getAttribute('name') || attributes[i].getAttribute('ref'); - var projectAttr = setupNode.getAttribute(attributeName); - projectAttr = this.processAttribute(projectAttr,attributes[i],this.schema); - switch(typeof projectAttr) - { - case "number": - case "boolean": - eval('this.'+attributeName+' = '+projectAttr); - break; - case "string": - eval('this.'+attributeName+' = "'+projectAttr+'"'); - break; - } - - } - + if (attribute == null) { + return attribute; + } + switch (dataType) { + case "boolean": + if (attribute == 'true') { + attribute = true; + } else { + attribute = false; + } + break; + case "negativeInteger": + case "positiveInteger": + case "nonNegativeInteger": + case "nonPositiveInteger": + case "integer": + case "decimal": + case "short": + attribute = Number(attribute); + break; + case "string": + default: + attribute = String(attribute); + break; + } + return attribute; + }; + + this.decode = function (projectXML) { + this.errors = []; + // projectXML - DOM Parsed document + this.projectXML = projectXML.childNodes[0]; + var setupNode = projectXML.getElementsByTagName('setup')[0]; + var schemaSetup = this.schema.getAllElementsByName('setup')[0]; + // First decode the attributes + var attributes = schemaSetup.getAllElementsByTagName('xs:attribute'); + for (var i = 0; i < attributes.length; i++) { + var attributeName = attributes[i].getAttribute('name') || attributes[i].getAttribute('ref'); + var projectAttr = setupNode.getAttribute(attributeName); + projectAttr = this.processAttribute(projectAttr, attributes[i], this.schema); + switch (typeof projectAttr) { + case "number": + case "boolean": + eval('this.' + attributeName + ' = ' + projectAttr); + break; + case "string": + eval('this.' + attributeName + ' = "' + projectAttr + '"'); + break; + } + + } + var exitTextNode = setupNode.getElementsByTagName('exitText'); if (exitTextNode.length == 1) { this.exitText = exitTextNode[0].textContent; } - - this.metrics = new this.metricNode(); - - this.metrics.decode(this,setupNode.getElementsByTagName('metric')[0]); - - // Now process the survey node options - var survey = setupNode.getElementsByTagName('survey'); - for (var i=0; i<survey.length; i++){ - var location = survey[i].getAttribute('location'); - switch(location) - { + + this.metrics = new this.metricNode(); + + this.metrics.decode(this, setupNode.getElementsByTagName('metric')[0]); + + // Now process the survey node options + var survey = setupNode.getElementsByTagName('survey'); + for (var i = 0; i < survey.length; i++) { + var location = survey[i].getAttribute('location'); + switch (location) { case 'pre': case 'before': - this.preTest = new this.surveyNode(this); - this.preTest.decode(this,survey[i]); + this.preTest = new this.surveyNode(this); + this.preTest.decode(this, survey[i]); break; case 'post': case 'after': this.postTest = new this.surveyNode(this); - this.postTest.decode(this,survey[i]); + this.postTest.decode(this, survey[i]); break; } - } - - var interfaceNode = setupNode.getElementsByTagName('interface'); - if (interfaceNode.length > 1) - { - this.errors.push("Only one <interface> node in the <setup> node allowed! Others except first ingnored!"); - } - this.interfaces = new this.interfaceNode(this); - if (interfaceNode.length != 0) - { - interfaceNode = interfaceNode[0]; - this.interfaces.decode(this,interfaceNode,this.schema.getAllElementsByName('interface')[1]); - } - - // Page tags - var pageTags = projectXML.getElementsByTagName('page'); - var pageSchema = this.schema.getAllElementsByName('page')[0]; - for (var i=0; i<pageTags.length; i++) - { - var node = new this.page(this); - node.decode(this,pageTags[i],pageSchema); - this.pages.push(node); - } - }; - - this.encode = function() - { - var RootDocument = document.implementation.createDocument(null,"waet"); - var root = RootDocument.firstChild; - root.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); - root.setAttribute("xsi:noNamespaceSchemaLocation","test-schema.xsd"); - // Build setup node + } + + var interfaceNode = setupNode.getElementsByTagName('interface'); + if (interfaceNode.length > 1) { + this.errors.push("Only one <interface> node in the <setup> node allowed! Others except first ingnored!"); + } + this.interfaces = new this.interfaceNode(this); + if (interfaceNode.length != 0) { + interfaceNode = interfaceNode[0]; + this.interfaces.decode(this, interfaceNode, this.schema.getAllElementsByName('interface')[1]); + } + + // Page tags + var pageTags = projectXML.getElementsByTagName('page'); + var pageSchema = this.schema.getAllElementsByName('page')[0]; + for (var i = 0; i < pageTags.length; i++) { + var node = new this.page(this); + node.decode(this, pageTags[i], pageSchema); + this.pages.push(node); + } + }; + + this.encode = function () { + var RootDocument = document.implementation.createDocument(null, "waet"); + var root = RootDocument.firstChild; + root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + root.setAttribute("xsi:noNamespaceSchemaLocation", "test-schema.xsd"); + // Build setup node var setup = RootDocument.createElement("setup"); var schemaSetup = this.schema.getAllElementsByName('setup')[0]; // First decode the attributes var attributes = schemaSetup.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributes.length; i++) - { + for (var i = 0; i < attributes.length; i++) { var name = attributes[i].getAttribute("name"); if (name == undefined) { name = attributes[i].getAttribute("ref"); } - if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required") - { - eval("setup.setAttribute('"+name+"',this."+name+")"); + if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { + eval("setup.setAttribute('" + name + "',this." + name + ")"); } } root.appendChild(setup); @@ -188,73 +180,71 @@ setup.appendChild(this.postTest.encode(RootDocument)); setup.appendChild(this.metrics.encode(RootDocument)); setup.appendChild(this.interfaces.encode(RootDocument)); - for (var page of this.pages) - { + for (var page of this.pages) { root.appendChild(page.encode(RootDocument)); } - return RootDocument; - }; - - this.surveyNode = function(specification) { - this.location = null; - this.options = []; + return RootDocument; + }; + + this.surveyNode = function (specification) { + this.location = null; + this.options = []; this.parent = null; - this.schema = specification.schema.getAllElementsByName('survey')[0]; + this.schema = specification.schema.getAllElementsByName('survey')[0]; this.specification = specification; - - this.OptionNode = function(specification) { - this.type = undefined; - this.schema = specification.schema.getAllElementsByName('surveyentry')[0]; - this.id = undefined; + + this.OptionNode = function (specification) { + this.type = undefined; + this.schema = specification.schema.getAllElementsByName('surveyentry')[0]; + this.id = undefined; this.name = undefined; - this.mandatory = undefined; - this.statement = undefined; - this.boxsize = undefined; - this.options = []; - this.min = undefined; - this.max = undefined; - this.step = undefined; + this.mandatory = undefined; + this.statement = undefined; + this.boxsize = undefined; + this.options = []; + this.min = undefined; + this.max = undefined; + this.step = undefined; this.conditions = []; - - this.decode = function(parent,child) - { - var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i in attributeMap){ - if(isNaN(Number(i)) == true){break;} - var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); - var projectAttr = child.getAttribute(attributeName); - projectAttr = parent.processAttribute(projectAttr,attributeMap[i],parent.schema); - switch(typeof projectAttr) - { - case "number": - case "boolean": - eval('this.'+attributeName+' = '+projectAttr); - break; - case "string": - eval('this.'+attributeName+' = "'+projectAttr+'"'); - break; - } - } - this.statement = child.getElementsByTagName('statement')[0].textContent; - if (this.type == "checkbox" || this.type == "radio") { - var children = child.getElementsByTagName('option'); - if (children.length == null) { - console.log('Malformed' +child.nodeName+ 'entry'); - this.statement = 'Malformed' +child.nodeName+ 'entry'; - this.type = 'statement'; - } else { - this.options = []; - for (var i=0; i<children.length; i++) - { - this.options.push({ - name: children[i].getAttribute('name'), - text: children[i].textContent - }); - } - } - } + + this.decode = function (parent, child) { + var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); + for (var i in attributeMap) { + if (isNaN(Number(i)) == true) { + break; + } + var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); + var projectAttr = child.getAttribute(attributeName); + projectAttr = parent.processAttribute(projectAttr, attributeMap[i], parent.schema); + switch (typeof projectAttr) { + case "number": + case "boolean": + eval('this.' + attributeName + ' = ' + projectAttr); + break; + case "string": + eval('this.' + attributeName + ' = "' + projectAttr + '"'); + break; + } + } + this.statement = child.getElementsByTagName('statement')[0].textContent; + if (this.type == "checkbox" || this.type == "radio") { + var children = child.getElementsByTagName('option'); + if (children.length == null) { + console.log('Malformed' + child.nodeName + 'entry'); + this.statement = 'Malformed' + child.nodeName + 'entry'; + this.type = 'statement'; + } else { + this.options = []; + for (var i = 0; i < children.length; i++) { + this.options.push({ + name: children[i].getAttribute('name'), + text: children[i].textContent + }); + } + } + } var conditionElements = child.getElementsByTagName("conditional"); - for (var i=0; i<conditionElements.length; i++) { + for (var i = 0; i < conditionElements.length; i++) { var condition = conditionElements[i]; var obj = { check: condition.getAttribute("check"), @@ -264,185 +254,193 @@ } this.conditions.push(obj); } - }; - - this.exportXML = function(doc) - { - var node = doc.createElement('surveyentry'); - node.setAttribute('type',this.type); - var statement = doc.createElement('statement'); - statement.textContent = this.statement; - node.appendChild(statement); + }; + + this.exportXML = function (doc) { + var node = doc.createElement('surveyentry'); + node.setAttribute('type', this.type); + var statement = doc.createElement('statement'); + statement.textContent = this.statement; + node.appendChild(statement); node.id = this.id; - if (this.name != undefined) { node.setAttribute("name",this.name);} - if (this.mandatory != undefined) { node.setAttribute("mandatory",this.mandatory);} + if (this.name != undefined) { + node.setAttribute("name", this.name); + } + if (this.mandatory != undefined) { + node.setAttribute("mandatory", this.mandatory); + } node.id = this.id; - if (this.name != undefined) {node.setAttribute("name",this.name);} - switch(this.type) - { + if (this.name != undefined) { + node.setAttribute("name", this.name); + } + switch (this.type) { case "checkbox": case "radio": - for (var i=0; i<this.options.length; i++) - { + for (var i = 0; i < this.options.length; i++) { var option = this.options[i]; var optionNode = doc.createElement("option"); - optionNode.setAttribute("name",option.name); + optionNode.setAttribute("name", option.name); optionNode.textContent = option.text; node.appendChild(optionNode); } case "number": - if (this.min != undefined) {node.setAttribute("min", this.min);} - if (this.max != undefined) {node.setAttribute("max", this.max);} + if (this.min != undefined) { + node.setAttribute("min", this.min); + } + if (this.max != undefined) { + node.setAttribute("max", this.max); + } case "question": - if (this.boxsize != undefined) {node.setAttribute("boxsize",this.boxsize);} - if (this.mandatory != undefined) {node.setAttribute("mandatory",this.mandatory);} + if (this.boxsize != undefined) { + node.setAttribute("boxsize", this.boxsize); + } + if (this.mandatory != undefined) { + node.setAttribute("mandatory", this.mandatory); + } default: break; } for (var condition of this.conditions) { var conditionDOM = doc.createElement("conditional"); - conditionDOM.setAttribute("check",condition.check); - conditionDOM.setAttribute("value",condition.value); - conditionDOM.setAttribute("jumpToOnPass",condition.jumpToOnPass); - conditionDOM.setAttribute("jumpToOnFail",condition.jumpToOnFail); + conditionDOM.setAttribute("check", condition.check); + conditionDOM.setAttribute("value", condition.value); + conditionDOM.setAttribute("jumpToOnPass", condition.jumpToOnPass); + conditionDOM.setAttribute("jumpToOnFail", condition.jumpToOnFail); node.appendChild(conditionDOM); } - return node; - }; - }; - this.decode = function(parent,xml) { + return node; + }; + }; + this.decode = function (parent, xml) { this.parent = parent; - this.location = xml.getAttribute('location'); - if (this.location == 'before'){this.location = 'pre';} - else if (this.location == 'after'){this.location = 'post';} + this.location = xml.getAttribute('location'); + if (this.location == 'before') { + this.location = 'pre'; + } else if (this.location == 'after') { + this.location = 'post'; + } var children = xml.getAllElementsByTagName('surveyentry'); - for (var i=0; i<children.length; i++) - { - var node = new this.OptionNode(this.specification); - node.decode(parent,children[i]); - this.options.push(node); - } + for (var i = 0; i < children.length; i++) { + var node = new this.OptionNode(this.specification); + node.decode(parent, children[i]); + this.options.push(node); + } if (this.options.length == 0) { console.log("Empty survey node"); console.log(this); } - }; - this.encode = function(doc) { - var node = doc.createElement('survey'); - node.setAttribute('location',this.location); - for (var i=0; i<this.options.length; i++) - { - node.appendChild(this.options[i].exportXML(doc)); - } - return node; - }; - }; - - this.interfaceNode = function(specification) - { - this.title = null; - this.name = null; - this.options = []; - this.scales = []; - this.schema = specification.schema.getAllElementsByName('interface')[1]; - - this.decode = function(parent,xml) { - this.name = xml.getAttribute('name'); - var titleNode = xml.getElementsByTagName('title'); - if (titleNode.length == 1) - { - this.title = titleNode[0].textContent; - } - var interfaceOptionNodes = xml.getElementsByTagName('interfaceoption'); - // Extract interfaceoption node schema - var interfaceOptionNodeSchema = this.schema.getAllElementsByName('interfaceoption')[0]; - var attributeMap = interfaceOptionNodeSchema.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<interfaceOptionNodes.length; i++) - { - var ioNode = interfaceOptionNodes[i]; - var option = {}; - for (var j=0; j<attributeMap.length; j++) - { - var attributeName = attributeMap[j].getAttribute('name') || attributeMap[j].getAttribute('ref'); - var projectAttr = ioNode.getAttribute(attributeName); - if(parent.processAttribute) { + }; + this.encode = function (doc) { + var node = doc.createElement('survey'); + node.setAttribute('location', this.location); + for (var i = 0; i < this.options.length; i++) { + node.appendChild(this.options[i].exportXML(doc)); + } + return node; + }; + }; + + this.interfaceNode = function (specification) { + this.title = null; + this.name = null; + this.options = []; + this.scales = []; + this.schema = specification.schema.getAllElementsByName('interface')[1]; + + this.decode = function (parent, xml) { + this.name = xml.getAttribute('name'); + var titleNode = xml.getElementsByTagName('title'); + if (titleNode.length == 1) { + this.title = titleNode[0].textContent; + } + var interfaceOptionNodes = xml.getElementsByTagName('interfaceoption'); + // Extract interfaceoption node schema + var interfaceOptionNodeSchema = this.schema.getAllElementsByName('interfaceoption')[0]; + var attributeMap = interfaceOptionNodeSchema.getAllElementsByTagName('xs:attribute'); + for (var i = 0; i < interfaceOptionNodes.length; i++) { + var ioNode = interfaceOptionNodes[i]; + var option = {}; + for (var j = 0; j < attributeMap.length; j++) { + var attributeName = attributeMap[j].getAttribute('name') || attributeMap[j].getAttribute('ref'); + var projectAttr = ioNode.getAttribute(attributeName); + if (parent.processAttribute) { parent.processAttribute(projectAttr, attributeMap[j], parent.schema) } else { parent.parent.processAttribute(projectAttr, attributeMap[j], parent.parent.schema) } - switch(typeof projectAttr) - { - case "number": - case "boolean": - eval('option.'+attributeName+' = '+projectAttr); - break; - case "string": - eval('option.'+attributeName+' = "'+projectAttr+'"'); - break; - } - } - this.options.push(option); - } - - // Now the scales nodes - var scaleParent = xml.getElementsByTagName('scales'); - if (scaleParent.length == 1) { - scaleParent = scaleParent[0]; + switch (typeof projectAttr) { + case "number": + case "boolean": + eval('option.' + attributeName + ' = ' + projectAttr); + break; + case "string": + eval('option.' + attributeName + ' = "' + projectAttr + '"'); + break; + } + } + this.options.push(option); + } + + // Now the scales nodes + var scaleParent = xml.getElementsByTagName('scales'); + if (scaleParent.length == 1) { + scaleParent = scaleParent[0]; var scalelabels = scaleParent.getAllElementsByTagName('scalelabel'); - for (var i=0; i<scalelabels.length; i++) { - this.scales.push({ - text: scalelabels[i].textContent, - position: Number(scalelabels[i].getAttribute('position')) - }); - } - } - }; - - this.encode = function(doc) { - var node = doc.createElement("interface"); + for (var i = 0; i < scalelabels.length; i++) { + this.scales.push({ + text: scalelabels[i].textContent, + position: Number(scalelabels[i].getAttribute('position')) + }); + } + } + }; + + this.encode = function (doc) { + var node = doc.createElement("interface"); if (typeof name == "string") - node.setAttribute("name",this.name); + node.setAttribute("name", this.name); if (typeof this.title == "string") { var titleNode = doc.createElement("title"); titleNode.textContent = this.title; node.appendChild(titleNode); } - for (var option of this.options) - { + for (var option of this.options) { var child = doc.createElement("interfaceoption"); - child.setAttribute("type",option.type); - child.setAttribute("name",option.name); + child.setAttribute("type", option.type); + child.setAttribute("name", option.name); node.appendChild(child); } if (this.scales.length != 0) { var scales = doc.createElement("scales"); - for (var scale of this.scales) - { + for (var scale of this.scales) { var child = doc.createElement("scalelabel"); - child.setAttribute("position",scale.position); + child.setAttribute("position", scale.position); child.textContent = scale.text; scales.appendChild(child); } node.appendChild(scales); } return node; - }; - }; - - this.metricNode = function() { + }; + }; + + this.metricNode = function () { this.enabled = []; - this.decode = function(parent, xml) { + this.decode = function (parent, xml) { var children = xml.getElementsByTagName('metricenable'); - for (var i in children) { - if (isNaN(Number(i)) == true){break;} + for (var i in children) { + if (isNaN(Number(i)) == true) { + break; + } this.enabled.push(children[i].textContent); } } - this.encode = function(doc) { + this.encode = function (doc) { var node = doc.createElement('metric'); - for (var i in this.enabled) - { - if (isNaN(Number(i)) == true){break;} + for (var i in this.enabled) { + if (isNaN(Number(i)) == true) { + break; + } var child = doc.createElement('metricenable'); child.textContent = this.enabled[i]; node.appendChild(child); @@ -450,248 +448,232 @@ return node; } } - - this.page = function(specification) { - this.presentedId = undefined; - this.id = undefined; + + this.page = function (specification) { + this.presentedId = undefined; + this.id = undefined; this.title = undefined; - this.hostURL = undefined; - this.randomiseOrder = undefined; - this.loop = undefined; - this.outsideReference = null; - this.loudness = null; + this.hostURL = undefined; + this.randomiseOrder = undefined; + this.loop = undefined; + this.outsideReference = null; + this.loudness = null; this.label = null; - this.preTest = null; - this.postTest = null; - this.interfaces = []; + this.preTest = null; + this.postTest = null; + this.interfaces = []; this.playOne = null; - this.commentBoxPrefix = "Comment on track"; - this.audioElements = []; - this.commentQuestions = []; - this.schema = specification.schema.getAllElementsByName("page")[0]; + this.commentBoxPrefix = "Comment on track"; + this.audioElements = []; + this.commentQuestions = []; + this.schema = specification.schema.getAllElementsByName("page")[0]; this.specification = specification; this.parent = null; - - this.decode = function(parent,xml) - { + + this.decode = function (parent, xml) { this.parent = parent; - var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributeMap.length; i++) - { - var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); - var projectAttr = xml.getAttribute(attributeName); - projectAttr = parent.processAttribute(projectAttr,attributeMap[i],parent.schema); - switch(typeof projectAttr) - { - case "number": - case "boolean": - eval('this.'+attributeName+' = '+projectAttr); - break; - case "string": - eval('this.'+attributeName+' = "'+projectAttr+'"'); - break; - } - } - + var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); + for (var i = 0; i < attributeMap.length; i++) { + var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); + var projectAttr = xml.getAttribute(attributeName); + projectAttr = parent.processAttribute(projectAttr, attributeMap[i], parent.schema); + switch (typeof projectAttr) { + case "number": + case "boolean": + eval('this.' + attributeName + ' = ' + projectAttr); + break; + case "string": + eval('this.' + attributeName + ' = "' + projectAttr + '"'); + break; + } + } + // Get the title var title = xml.getElementsByTagName('title'); if (title.length != 0 && title[0].parentElement == xml) { this.title = title[0].textContent; } - - // Get the Comment Box Prefix - var CBP = xml.getElementsByTagName('commentboxprefix'); - if (CBP.length != 0 && CBP[0].parentElement == xml) { - this.commentBoxPrefix = CBP[0].textContent; - } - - // Now decode the interfaces - var interfaceNode = xml.getElementsByTagName('interface'); - for (var i=0; i<interfaceNode.length; i++) - { - var node = new parent.interfaceNode(this.specification); - node.decode(this,interfaceNode[i],parent.schema.getAllElementsByName('interface')[1]); - this.interfaces.push(node); - } - - // Now process the survey node options - var survey = xml.getElementsByTagName('survey'); - var surveySchema = parent.schema.getAllElementsByName('survey')[0]; - for (var i=0; i<survey.length; i++){ - var location = survey[i].getAttribute('location'); - if (location == 'pre' || location == 'before') - { - if (this.preTest != null){this.errors.push("Already a pre/before test survey defined! Ignoring second!!");} - else { - this.preTest = new parent.surveyNode(this.specification); - this.preTest.decode(parent,survey[i],surveySchema); - } - } else if (location == 'post' || location == 'after') { - if (this.postTest != null){this.errors.push("Already a post/after test survey defined! Ignoring second!!");} - else { - this.postTest = new parent.surveyNode(this.specification); - this.postTest.decode(parent,survey[i],surveySchema); - } - } - } - - // Now process the audioelement tags - var audioElements = xml.getElementsByTagName('audioelement'); - for (var i=0; i<audioElements.length; i++) - { - var node = new this.audioElementNode(this.specification); - node.decode(this,audioElements[i]); - this.audioElements.push(node); - } - - // Now decode the commentquestions - var commentQuestions = xml.getElementsByTagName('commentquestion'); - for (var i=0; i<commentQuestions.length; i++) - { - var node = new this.commentQuestionNode(this.specification); - node.decode(parent,commentQuestions[i]); - this.commentQuestions.push(node); - } - }; - - this.encode = function(root) - { - var AHNode = root.createElement("page"); + + // Get the Comment Box Prefix + var CBP = xml.getElementsByTagName('commentboxprefix'); + if (CBP.length != 0 && CBP[0].parentElement == xml) { + this.commentBoxPrefix = CBP[0].textContent; + } + + // Now decode the interfaces + var interfaceNode = xml.getElementsByTagName('interface'); + for (var i = 0; i < interfaceNode.length; i++) { + var node = new parent.interfaceNode(this.specification); + node.decode(this, interfaceNode[i], parent.schema.getAllElementsByName('interface')[1]); + this.interfaces.push(node); + } + + // Now process the survey node options + var survey = xml.getElementsByTagName('survey'); + var surveySchema = parent.schema.getAllElementsByName('survey')[0]; + for (var i = 0; i < survey.length; i++) { + var location = survey[i].getAttribute('location'); + if (location == 'pre' || location == 'before') { + if (this.preTest != null) { + this.errors.push("Already a pre/before test survey defined! Ignoring second!!"); + } else { + this.preTest = new parent.surveyNode(this.specification); + this.preTest.decode(parent, survey[i], surveySchema); + } + } else if (location == 'post' || location == 'after') { + if (this.postTest != null) { + this.errors.push("Already a post/after test survey defined! Ignoring second!!"); + } else { + this.postTest = new parent.surveyNode(this.specification); + this.postTest.decode(parent, survey[i], surveySchema); + } + } + } + + // Now process the audioelement tags + var audioElements = xml.getElementsByTagName('audioelement'); + for (var i = 0; i < audioElements.length; i++) { + var node = new this.audioElementNode(this.specification); + node.decode(this, audioElements[i]); + this.audioElements.push(node); + } + + // Now decode the commentquestions + var commentQuestions = xml.getElementsByTagName('commentquestion'); + for (var i = 0; i < commentQuestions.length; i++) { + var node = new this.commentQuestionNode(this.specification); + node.decode(parent, commentQuestions[i]); + this.commentQuestions.push(node); + } + }; + + this.encode = function (root) { + var AHNode = root.createElement("page"); // First decode the attributes var attributes = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributes.length; i++) - { + for (var i = 0; i < attributes.length; i++) { var name = attributes[i].getAttribute("name"); if (name == undefined) { name = attributes[i].getAttribute("ref"); } - if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required") - { - eval("AHNode.setAttribute('"+name+"',this."+name+")"); + if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { + eval("AHNode.setAttribute('" + name + "',this." + name + ")"); } } - if(this.loudness != null) {AHNode.setAttribute("loudness",this.loudness);} + if (this.loudness != null) { + AHNode.setAttribute("loudness", this.loudness); + } // <commentboxprefix> var commentboxprefix = root.createElement("commentboxprefix"); commentboxprefix.textContent = this.commentBoxPrefix; AHNode.appendChild(commentboxprefix); - - for (var i=0; i<this.interfaces.length; i++) - { - AHNode.appendChild(this.interfaces[i].encode(root)); - } - - for (var i=0; i<this.audioElements.length; i++) { - AHNode.appendChild(this.audioElements[i].encode(root)); - } - // Create <CommentQuestion> - for (var i=0; i<this.commentQuestions.length; i++) - { - AHNode.appendChild(this.commentQuestions[i].encode(root)); - } - - AHNode.appendChild(this.preTest.encode(root)); + + for (var i = 0; i < this.interfaces.length; i++) { + AHNode.appendChild(this.interfaces[i].encode(root)); + } + + for (var i = 0; i < this.audioElements.length; i++) { + AHNode.appendChild(this.audioElements[i].encode(root)); + } + // Create <CommentQuestion> + for (var i = 0; i < this.commentQuestions.length; i++) { + AHNode.appendChild(this.commentQuestions[i].encode(root)); + } + + AHNode.appendChild(this.preTest.encode(root)); AHNode.appendChild(this.postTest.encode(root)); - return AHNode; - }; - - this.commentQuestionNode = function(specification) { - this.id = null; + return AHNode; + }; + + this.commentQuestionNode = function (specification) { + this.id = null; this.name = undefined; - this.type = undefined; - this.options = []; - this.statement = undefined; - this.schema = specification.schema.getAllElementsByName('commentquestion')[0]; - this.decode = function(parent,xml) - { - this.id = xml.id; + this.type = undefined; + this.options = []; + this.statement = undefined; + this.schema = specification.schema.getAllElementsByName('commentquestion')[0]; + this.decode = function (parent, xml) { + this.id = xml.id; this.name = xml.getAttribute('name'); - this.type = xml.getAttribute('type'); - this.statement = xml.getElementsByTagName('statement')[0].textContent; - var optNodes = xml.getElementsByTagName('option'); - for (var i=0; i<optNodes.length; i++) - { - var optNode = optNodes[i]; - this.options.push({ - name: optNode.getAttribute('name'), - text: optNode.textContent - }); - } - }; - - this.encode = function(root) - { - var node = root.createElement("commentquestion"); + this.type = xml.getAttribute('type'); + this.statement = xml.getElementsByTagName('statement')[0].textContent; + var optNodes = xml.getElementsByTagName('option'); + for (var i = 0; i < optNodes.length; i++) { + var optNode = optNodes[i]; + this.options.push({ + name: optNode.getAttribute('name'), + text: optNode.textContent + }); + } + }; + + this.encode = function (root) { + var node = root.createElement("commentquestion"); node.id = this.id; - node.setAttribute("type",this.type); - if (this.name != undefined){node.setAttribute("name",this.name);} + node.setAttribute("type", this.type); + if (this.name != undefined) { + node.setAttribute("name", this.name); + } var statement = root.createElement("statement"); statement.textContent = this.statement; node.appendChild(statement); - for (var option of this.options) - { + for (var option of this.options) { var child = root.createElement("option"); - child.setAttribute("name",option.name); + child.setAttribute("name", option.name); child.textContent = option.text; node.appendChild(child); } return node; - }; - }; - - this.audioElementNode = function(specification) { - this.url = null; - this.id = null; + }; + }; + + this.audioElementNode = function (specification) { + this.url = null; + this.id = null; this.name = null; - this.parent = null; - this.type = null; - this.marker = null; - this.enforce = false; - this.gain = 0.0; + this.parent = null; + this.type = null; + this.marker = null; + this.enforce = false; + this.gain = 0.0; this.label = null; this.startTime = undefined; this.stopTime = undefined; - this.schema = specification.schema.getAllElementsByName('audioelement')[0];; - this.parent = null; - this.decode = function(parent,xml) - { - this.parent = parent; - var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributeMap.length; i++) - { - var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); - var projectAttr = xml.getAttribute(attributeName); - projectAttr = parent.parent.processAttribute(projectAttr,attributeMap[i],parent.parent.schema); - switch(typeof projectAttr) - { - case "number": - case "boolean": - eval('this.'+attributeName+' = '+projectAttr); - break; - case "string": - eval('this.'+attributeName+' = "'+projectAttr+'"'); - break; - } - } - - }; - this.encode = function(root) - { - var AENode = root.createElement("audioelement"); - var attributes = this.schema.getAllElementsByTagName('xs:attribute'); - for (var i=0; i<attributes.length; i++) - { + this.schema = specification.schema.getAllElementsByName('audioelement')[0];; + this.parent = null; + this.decode = function (parent, xml) { + this.parent = parent; + var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); + for (var i = 0; i < attributeMap.length; i++) { + var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); + var projectAttr = xml.getAttribute(attributeName); + projectAttr = parent.parent.processAttribute(projectAttr, attributeMap[i], parent.parent.schema); + switch (typeof projectAttr) { + case "number": + case "boolean": + eval('this.' + attributeName + ' = ' + projectAttr); + break; + case "string": + eval('this.' + attributeName + ' = "' + projectAttr + '"'); + break; + } + } + + }; + this.encode = function (root) { + var AENode = root.createElement("audioelement"); + var attributes = this.schema.getAllElementsByTagName('xs:attribute'); + for (var i = 0; i < attributes.length; i++) { var name = attributes[i].getAttribute("name"); if (name == undefined) { name = attributes[i].getAttribute("ref"); } - if(eval("this."+name+" != undefined") || attributes[i].getAttribute("use") == "required") - { - eval("AENode.setAttribute('"+name+"',this."+name+")"); + if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { + eval("AENode.setAttribute('" + name + "',this." + name + ")"); } } - return AENode; - }; - }; - }; + return AENode; + }; + }; + }; }
--- a/php/comment_parser.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/comment_parser.php Mon Nov 14 14:17:03 2016 +0000 @@ -148,4 +148,4 @@ } else { echo "FATAL - No saved XML files discovered"; } -?> \ No newline at end of file +?>
--- a/php/get_filtered_count.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/get_filtered_count.php Mon Nov 14 14:17:03 2016 +0000 @@ -107,4 +107,4 @@ echo '{"urls": ["'.implode('","',$files).'"]}'; } -?> \ No newline at end of file +?>
--- a/php/get_filtered_score.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/get_filtered_score.php Mon Nov 14 14:17:03 2016 +0000 @@ -196,4 +196,4 @@ } echo $doc_string; } -?> \ No newline at end of file +?>
--- a/php/get_tests.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/get_tests.php Mon Nov 14 14:17:03 2016 +0000 @@ -68,4 +68,4 @@ echo '{"error": "format can only be JSON"}'; } -?> \ No newline at end of file +?>
--- a/php/pool.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/pool.php Mon Nov 14 14:17:03 2016 +0000 @@ -109,4 +109,4 @@ echo $new_doc->saveXML(); -?> \ No newline at end of file +?>
--- a/php/rel2abs.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/rel2abs.php Mon Nov 14 14:17:03 2016 +0000 @@ -29,4 +29,4 @@ /* absolute URL is ready! */ return $scheme.'://'.$abs; } -?> \ No newline at end of file +?>
--- a/php/save.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/save.php Mon Nov 14 14:17:03 2016 +0000 @@ -35,4 +35,4 @@ // Return XML confirmation data $xml = '<response state="OK"><message>OK</message><file bytes="'.$wbytes.'">"'.$filename.'"</file></response>'; echo $xml; -?> \ No newline at end of file +?>
--- a/php/score_parser.php Mon Nov 14 12:11:38 2016 +0000 +++ b/php/score_parser.php Mon Nov 14 14:17:03 2016 +0000 @@ -195,4 +195,4 @@ echo "FATAL - No saved XML files discovered"; } -?> \ No newline at end of file +?>
--- a/python/comment_parser.html Mon Nov 14 12:11:38 2016 +0000 +++ b/python/comment_parser.html Mon Nov 14 14:17:03 2016 +0000 @@ -1,72 +1,78 @@ <html lang="en"> - <head> - <meta charset="utf-8" /> - <script type="text/javascript"> - function getXML() - { - var XMLHttp = new XMLHttpRequest(); - XMLHttp.open("GET","comment_parser.php?format=XML",true); - XMLHttp.onload = function() { - // Now we have the XML data, extract - var parse = new DOMParser(); - var ajax = parse.parseFromString(XMLHttp.response,'text/xml'); - - var parent = document.createElement("div"); - parent.appendChild(ajax.children[0]); - var file = [parent.innerHTML]; - var bb = new Blob(file,{type : 'application/xml'}); - generateLink(bb,".xml"); - } - XMLHttp.send(); + +<head> + <meta charset="utf-8" /> + <script type="text/javascript"> + function getXML() { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET", "comment_parser.php?format=XML", true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var parse = new DOMParser(); + var ajax = parse.parseFromString(XMLHttp.response, 'text/xml'); + + var parent = document.createElement("div"); + parent.appendChild(ajax.children[0]); + var file = [parent.innerHTML]; + var bb = new Blob(file, { + type: 'application/xml' + }); + generateLink(bb, ".xml"); } - - function getJSON() - { - var XMLHttp = new XMLHttpRequest(); - XMLHttp.open("GET","comment_parser.php?format=JSON",true); - XMLHttp.onload = function() { - // Now we have the XML data, extract - var file = [XMLHttp.response]; - var bb = new Blob(file,{type : 'application/json'}); - generateLink(bb,".json"); - } - XMLHttp.send(); + XMLHttp.send(); + } + + function getJSON() { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET", "comment_parser.php?format=JSON", true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var file = [XMLHttp.response]; + var bb = new Blob(file, { + type: 'application/json' + }); + generateLink(bb, ".json"); } - - function getCSV() - { - var XMLHttp = new XMLHttpRequest(); - XMLHttp.open("GET","comment_parser.php?format=CSV",true); - XMLHttp.onload = function() { - // Now we have the XML data, extract - var file = [XMLHttp.response]; - var bb = new Blob(file,{type : 'text/csv'}); - generateLink(bb,".csv"); - } - XMLHttp.send(); + XMLHttp.send(); + } + + function getCSV() { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET", "comment_parser.php?format=CSV", true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var file = [XMLHttp.response]; + var bb = new Blob(file, { + type: 'text/csv' + }); + generateLink(bb, ".csv"); } - - function generateLink(blobfile,fmt) - { - var dnlk = window.URL.createObjectURL(blobfile); - var a = document.createElement("a"); - a.hidden = ''; - a.href = dnlk; - a.download = "save"+fmt; - a.textContent = "Save File"; - document.getElementById("download").appendChild(a); - } - </script> - </head> - <body> - <h1>WAET Test Results Analysis</h1> - <h2>Comment Extraction</h2> - <p>All of the XMLs in the server 'saves/' directory are automatically parsed and downloaded, extracting only the comments. Simply select the comments you wish to extract below and your desired data format.</p> - <div id="download"></div> - <div> - <button onclick="getXML();">XML</button> - <button onclick="getJSON();">JSON</button> - <button onclick="getCSV();">CSV</button> - </div> - </body> -</html> \ No newline at end of file + XMLHttp.send(); + } + + function generateLink(blobfile, fmt) { + var dnlk = window.URL.createObjectURL(blobfile); + var a = document.createElement("a"); + a.hidden = ''; + a.href = dnlk; + a.download = "save" + fmt; + a.textContent = "Save File"; + document.getElementById("download").appendChild(a); + } + + </script> +</head> + +<body> + <h1>WAET Test Results Analysis</h1> + <h2>Comment Extraction</h2> + <p>All of the XMLs in the server 'saves/' directory are automatically parsed and downloaded, extracting only the comments. Simply select the comments you wish to extract below and your desired data format.</p> + <div id="download"></div> + <div> + <button onclick="getXML();">XML</button> + <button onclick="getJSON();">JSON</button> + <button onclick="getCSV();">CSV</button> + </div> +</body> + +</html>
--- a/test.html Mon Nov 14 12:11:38 2016 +0000 +++ b/test.html Mon Nov 14 14:17:03 2016 +0000 @@ -1,41 +1,43 @@ <!DOCTYPE html> <html lang="en"> - <head> - <meta http-equiv="content-type" content="text/html; charset=utf-8"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> - <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame + + <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame Remove this if you use the .htaccess --> - <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> - <title>Web Audio Evaluation Tool</title> - <meta name="description" content="" /> - <meta name="author" content="" /> - - <!-- Load up the default core JS and CSS files--> - <link rel='stylesheet' type='text/css' href='css/core.css'> - <!-- Use jQuery hosted from Google CDN --> - <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>--> - <script type="text/javascript" src="js/jquery-2.1.4.js"></script> - <script type="text/javascript" src="js/loader.js"></script> - </head> + <title>Web Audio Evaluation Tool</title> + <meta name="description" content="" /> + <meta name="author" content="" /> - <body> - <!-- Load up the default page interface allowing for project setting loads, even if hard-coded--> - <!-- Actual test interface design should be contained in the .js for ease of dynamic content--> - <div id='topLevelBody'> - <span>Web Audio Evaluation Toolbox</span> - </div> - <div id="popupHolder" class="popupHolder" style="visibility: hidden"> - <div id="popupContent"> - <div id="popupTitleHolder"> - <span id="popupTitle"></span> - </div> - <div id="popupResponse"></div> + <!-- Load up the default core JS and CSS files--> + <link rel='stylesheet' type='text/css' href='css/core.css'> + <!-- Use jQuery hosted from Google CDN --> + <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>--> + <script type="text/javascript" src="js/jquery-2.1.4.js"></script> + <script type="text/javascript" src="js/loader.js"></script> +</head> + +<body> + <!-- Load up the default page interface allowing for project setting loads, even if hard-coded--> + <!-- Actual test interface design should be contained in the .js for ease of dynamic content--> + <div id='topLevelBody'> + <span>Web Audio Evaluation Toolbox</span> + </div> + <div id="popupHolder" class="popupHolder" style="visibility: hidden"> + <div id="popupContent"> + <div id="popupTitleHolder"> + <span id="popupTitle"></span> </div> - <button id="popup-proceed" class="popupButton">Next</button> - <button id="popup-previous" class="popupButton">Back</button> + <div id="popupResponse"></div> </div> - <div class="testHalt" style="visibility: hidden"></div> - </body> + <button id="popup-proceed" class="popupButton">Next</button> + <button id="popup-previous" class="popupButton">Back</button> + </div> + <div class="testHalt" style="visibility: hidden"></div> +</body> + </html>
--- a/test_create.html Mon Nov 14 12:11:38 2016 +0000 +++ b/test_create.html Mon Nov 14 14:17:03 2016 +0000 @@ -1,20 +1,31 @@ <html> + <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <!-- This defines the test creator tool for the Web Audio Evaluation Toolbox --> - <link rel='stylesheet' type="text/css" href="test_create/style.css"/> - <link rel='stylesheet' type="text/css" href="test_create/custom.css"/> + <link rel='stylesheet' type="text/css" href="test_create/style.css" /> + <link rel='stylesheet' type="text/css" href="test_create/custom.css" /> <script type="text/javascript"> - window.onbeforeunload = function (e) {var message = 'If you leave the page now, any unsaved changes will be lost', e = e || window.event; if (e) { e.returnValue = message;}return message;}; + window.onbeforeunload = function(e) { + var message = 'If you leave the page now, any unsaved changes will be lost', + e = e || window.event; + if (e) { + e.returnValue = message; + } + return message; + }; // Copy of Specifiation node from Core.js + </script> <script src="js/jquery-2.1.4.js"></script> <script type="text/javascript" src='js/specification.js'></script> <script type="text/javascript" src="test_create/test_core.js"></script> </head> + <body> <div id="popupHolder"></div> <div id="blanket"></div> <div id="content"></div> </body> + </html>
--- a/test_create/custom.css Mon Nov 14 12:11:38 2016 +0000 +++ b/test_create/custom.css Mon Nov 14 14:17:03 2016 +0000 @@ -1,23 +1,20 @@ - -div#content > div.node{ - background-color: rgb(200,228,151); +div#content > div.node { + background-color: rgb(200, 228, 151); } - -div#content > div#setup{ +div#content > div#setup { background-color: coral; } - -input:disabled+span{ +input:disabled+span { text-decoration: line-through; } - -div.attribute{ +div.attribute { float: none; } -div.attribute input{ +div.attribute input { max-width: 100%; width: 300px; } -div.attribute input[type=radio], div.attribute input[type=checkbox]{ +div.attribute input[type=radio], +div.attribute input[type=checkbox] { width: 10px; -} \ No newline at end of file +}
--- a/test_create/interface-specs.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/test_create/interface-specs.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,532 +1,532 @@ <?xml version="1.0" encoding="UTF-8" ?> -<root> - <global> - <metrics> - <list name="testTimer">Test Timer</list> - <list name="elementTimer">Element Playback Timer</list> - <list name="elementInitialPosition">Element Initial Position</list> - <list name="elementTracker">Element Movement Tracker</list> - <list name="elementFlagListenedTo">Element Listened to Flag</list> - <list name="elementFlagMoved">Element Moved Flag</list> - <list name="elementListenTracker">Element Listen Tracker</list> - </metrics> - <checks> - <list name="fragmentMoved">Check all moved</list> - <list name="fragmentPlayed">Check all played</list> - <list name="fragmentFullPlayback">Check all fully played (non-loop only)</list> - <list name="fragmentComments">Check comments entered</list> - <list name="scalerange">Enforce scale usage range</list> - </checks> - <show> - <list name="volume">Show master volume control</list> - <list name="page-count">Show test page count</list> - <list name="playhead">Show playhead</list> - <list name="comments">Show element comment boxes</list> - </show> - </global> - <interfaces> - <interface name="APE"> + <root> + <global> <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="optional" default="on"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="optional" default="on"/> - <entry name="elementListenTracker" support="optional" default="on"/> + <list name="testTimer">Test Timer</list> + <list name="elementTimer">Element Playback Timer</list> + <list name="elementInitialPosition">Element Initial Position</list> + <list name="elementTracker">Element Movement Tracker</list> + <list name="elementFlagListenedTo">Element Listened to Flag</list> + <list name="elementFlagMoved">Element Moved Flag</list> + <list name="elementListenTracker">Element Listen Tracker</list> </metrics> <checks> - <entry name="fragmentMoved" support="optional" default="off"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="optional" default="off"/> + <list name="fragmentMoved">Check all moved</list> + <list name="fragmentPlayed">Check all played</list> + <list name="fragmentFullPlayback">Check all fully played (non-loop only)</list> + <list name="fragmentComments">Check comments entered</list> + <list name="scalerange">Enforce scale usage range</list> </checks> <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="on"/> + <list name="volume">Show master volume control</list> + <list name="page-count">Show test page count</list> + <list name="playhead">Show playhead</list> + <list name="comments">Show element comment boxes</list> </show> - <elements> - <number min="1" max="undefined"/> - <anchor min="0" max="undefined"/> - <reference min="0" max="undefined"/> - <outsidereference min="0" max="1"/> - </elements> - </interface> - <interface name="MUSHRA"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="optional" default="on"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="optional" default="on"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="optional" default="off"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="optional" default="off"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="1" max="undefined"/> - <anchor min="0" max="undefined"/> - <reference min="0" max="undefined"/> - <outsidereference min="0" max="1"/> - </elements> - </interface> - <interface name="horizontal"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="optional" default="on"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="optional" default="on"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="optional" default="off"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="optional" default="off"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="1" max="undefined"/> - <anchor min="0" max="undefined"/> - <reference min="0" max="undefined"/> - <outsidereference min="0" max="1"/> - </elements> - </interface> - <interface name="discrete"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="none"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="optional" default="on"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="mandatory"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="none"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="1" max="undefined"/> - <anchor min="0" max="undefined"/> - <reference min="0" max="undefined"/> - <outsidereference min="0" max="1"/> - </elements> - </interface> - <interface name="AB"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="none"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="none"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="none"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="2" max="undefined"/> - <anchor min="0" max="undefined"/> - <reference min="0" max="undefined"/> - <outsidereference min="0" max="1"/> - </elements> - </interface> - <interface name="ABX"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="none"/> - <entry name="elementTracker" support="optional" default="on"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="none"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="none"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="optional" default="off"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="2" max="2"/> - <anchor min="0" max="0"/> - <reference min="0" max="0"/> - <outsidereference min="0" max="0"/> - </elements> - </interface> - <interface name="timeline"> - <metrics> - <entry name="testTimer" support="optional" default="on"/> - <entry name="elementTimer" support="optional" default="on"/> - <entry name="elementInitialPosition" support="none"/> - <entry name="elementTracker" support="none" default="off"/> - <entry name="elementFlagListenedTo" support="optional" default="on"/> - <entry name="elementFlagMoved" support="none"/> - <entry name="elementListenTracker" support="optional" default="on"/> - </metrics> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="optional" default="off"/> - <entry name="fragmentFullPlayback" support="optional" default="off"/> - <entry name="fragmentComments" support="optional" default="off"/> - <entry name="scalerange" support="none"/> - </checks> - <show> - <entry name="volume" support="optional" default="off"/> - <entry name="page-count" support="optional" default="off"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="optional" default="off"/> - </show> - <elements> - <number min="1" max="undefined"/> - <anchor min="0" max="0"/> - <reference min="0" max="0"/> - <outsidereference min="0" max="undefined"/> - </elements> - </interface> - </interfaces> - <scaledefinitions> - <scale name="(Blank)"> - </scale> - <scale name="Likert"> - <scalelabel position="0">Strongly Disagree</scalelabel> - <scalelabel position="25">Disagree</scalelabel> - <scalelabel position="50">Neutral</scalelabel> - <scalelabel position="75">Agree</scalelabel> - <scalelabel position="100">Strongly Agree</scalelabel> - </scale> - <scale name="ABC"> - <scalelabel position="100">Imperceptible</scalelabel> - <scalelabel position="75">Perceptible but not annoying</scalelabel> - <scalelabel position="50">Slightly annoying</scalelabel> - <scalelabel position="25">Annoying</scalelabel> - <scalelabel position="0">Very annoying</scalelabel> - </scale> - <scale name="Bipolar"> - <scalelabel position="0">-50</scalelabel> - <scalelabel position="50">0</scalelabel> - <scalelabel position="100">50</scalelabel> - </scale> - <scale name="ACR"> - <scalelabel position="0">Bad</scalelabel> - <scalelabel position="25">Poor</scalelabel> - <scalelabel position="50">Fair</scalelabel> - <scalelabel position="75">Good</scalelabel> - <scalelabel position="100">Excellent</scalelabel> - </scale> - <scale name="DCR"> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scale> - <scale name="CCR"> - <scalelabel position="12">Much Worse</scalelabel> - <scalelabel position="25">Worse</scalelabel> - <scalelabel position="38">Slightly Worse</scalelabel> - <scalelabel position="50">About the same</scalelabel> - <scalelabel position="62">Slightly Better</scalelabel> - <scalelabel position="75">Better</scalelabel> - <scalelabel position="88">Much Better</scalelabel> - </scale> - <scale name="HCRS"> - <scalelabel position="10">Dislike Extremely</scalelabel> - <scalelabel position="20">Dislike Very Much</scalelabel> - <scalelabel position="30">Dislike Moderate</scalelabel> - <scalelabel position="40">Dislike Slightly</scalelabel> - <scalelabel position="50">Neither Like nor Dislike</scalelabel> - <scalelabel position="60">Like Slightly</scalelabel> - <scalelabel position="70">Like Moderate</scalelabel> - <scalelabel position="80">Like Very Much</scalelabel> - <scalelabel position="90">Like Extremely</scalelabel> - </scale> - </scaledefinitions> - <tests> - <test name="APE" interface="APE"> - <descriptions> - <description lang="en">Audio Perceptual Evaluation. A multi-stimulus test where each audio fragment is shown on one continuous slider. Fragments are randomnly positioned along the slider. The user clicks a fragment to play and drags to move.</description> - </descriptions> - </test> - <test name="vertical-sliders" interface="MUSHRA"> - <descriptions> - <description lang="en">Each element is given its own vertical slider with user defined scale markers.</description> - </descriptions> - </test> - <test name="horizontal-sliders" interface="horizontal"> - <descriptions> - <description lang="en">Each element is given its own horizontal slider with user defined scale markers.</description> - </descriptions> - </test> - <test name="discrete" interface="discrete"> - <descriptions> - <description lang="en">Each element is given a horizontal scale broken into a number of discrete choices. The number of choices is defined by the scale markers.</description> - </descriptions> - </test> - <test name="Comparison" interface="AB"> - <descriptions> - <description lang="en">An N-way comparison test. Each element is given its own selector box. The user can select one element per page for submission.</description> - </descriptions> - </test> - <test name="MUSHRA" interface="MUSHRA"> - <descriptions> - <description lang="en">Multi-stimulus with hidden reference and anchor. Each fragment is shown on its own vertical slider. One fragment must be labelled as a reference and another labelled as an anchor. One external reference must also be shown.</description> - </descriptions> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - <entry name="scalerange" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <elements> - <anchor min="1" max="undefined"/> - <reference min="1" max="undefined"/> - <outsidereference min="1" max="1"/> - </elements> - <scale name="ACR"/> - </test> - <test name="Rank" interface="discrete"> - <descriptions> - <description lang="en">Each stimulus is placed on a discrete scale equalling the number of fragments. The fragments are then ranked based on the question posed. Only one element can occupy a rank position</description> - </descriptions> - <checks> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="undefined"/> - </test> - <test name="Likert" interface="discrete"> - <descriptions> - <description lang="en">Each stimulus is placed on a discrete scale. The scale is fixed to the Likert scale options of 'Strongly Disagree', 'Disagree', 'Neutral', 'Agree' and 'Strongly Agree'</description> - </descriptions> - <checks> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="Likert"/> - </test> - <test name="ABC/HR" interface="MUSHRA"> - <descriptions> - <description lang="en">Each stimulus is placed on a vertical slider. The scale is fixed with the labels 'Imperceptible' to 'Very Annoying'</description> - </descriptions> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="ABC"/> - </test> - <test name="Bipolar" interface="horizontal"> - <descriptions> - <description lang="en">Each stimulus is placed on a horizontal slider and initialised to the value '0'. The scale operates from -50 to +5-. In the results this is normalised, like all other interfaces, from 0 (-50) to 1 (+50).</description> - </descriptions> - <checks> - <entry name="fragmentMoved" support="mandatory"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <elements> - <outsidereference min="1" max="1"/> - </elements> - <scale name="Bipolar"/> - </test> - <test name="ACR" interface="discrete"> - <descriptions> - <description lang="en">Absolute Category Rating. Each element is on a discrete scale of 'Bad', 'Poor', 'Fair', 'Good' and 'Excellent'. Each element must be given a rating.</description> - </descriptions> - <checks> - <entry name="fragmentMoved" support="mandatory"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="ACR"/> - </test> - <test name="DCR" interface="discrete"> - <checks> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="DCR"/> - </test> - <test name="CCR" interface="discrete"> - <checks> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <scale name="CCR"/> - </test> - <test name="HCRS" interface="MUSHRA"> - <checks> - <entry name="fragmentMoved" support="mandatory"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <elements> - <outsidereference min="1" max="1"/> - </elements> - <scale name="HCRS"/> - </test> - <test name="ITUR5PCIS" interface="MUSHRA"> - <checks> - <entry name="fragmentMoved" support="none"/> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <elements> - <outsidereference min="1" max="1"/> - </elements> - <scale name="ABC"/> - </test> - <test name="AB" interface="AB"> - <descriptions> - <description lang="en">Each page has only two audio fragments. The user must select one of the two fragments to proceed. There can be one hidden reference.</description> - </descriptions> - <checks> - <entry name="fragmentPlayed" support="none"/> - <entry name="fragmentFullPlayback" support="none"/> - <entry name="fragmentComments" support="none"/> - </checks> - <show> - <entry name="volume" support="none"/> - <entry name="page-count" support="none"/> - <entry name="playhead" support="none"/> - <entry name="comments" support="none"/> - </show> - <elements> - <number min="2" max="2"/> - <outsidereference min="0" max="1"/> - </elements> - </test> - <test name="ABX" interface="ABX"> - <descriptions> - <description lang="en">Each page has two audio fragments presented as A and B. The test duplicates one of the fragments and presents it as X. The user must choose which, out of A or B, is closest to X.</description> - </descriptions> - </test> - <test name="timeline" interface="timeline"> - <descriptions> - <description lang="en">Each fragment is displayed with a clickable waveform of itself. The user must click on the waveform at the location that a specific event occured. Users can then enter in information about this event. This test is unit-/value-less.</description> - </descriptions> - </test> - </tests> -</root> \ No newline at end of file + </global> + <interfaces> + <interface name="APE"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="optional" default="on" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="optional" default="on" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="optional" default="off" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="optional" default="off" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="on" /> + </show> + <elements> + <number min="1" max="undefined" /> + <anchor min="0" max="undefined" /> + <reference min="0" max="undefined" /> + <outsidereference min="0" max="1" /> + </elements> + </interface> + <interface name="MUSHRA"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="optional" default="on" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="optional" default="on" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="optional" default="off" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="optional" default="off" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="1" max="undefined" /> + <anchor min="0" max="undefined" /> + <reference min="0" max="undefined" /> + <outsidereference min="0" max="1" /> + </elements> + </interface> + <interface name="horizontal"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="optional" default="on" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="optional" default="on" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="optional" default="off" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="optional" default="off" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="1" max="undefined" /> + <anchor min="0" max="undefined" /> + <reference min="0" max="undefined" /> + <outsidereference min="0" max="1" /> + </elements> + </interface> + <interface name="discrete"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="none" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="optional" default="on" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="mandatory" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="none" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="1" max="undefined" /> + <anchor min="0" max="undefined" /> + <reference min="0" max="undefined" /> + <outsidereference min="0" max="1" /> + </elements> + </interface> + <interface name="AB"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="none" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="none" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="none" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="2" max="undefined" /> + <anchor min="0" max="undefined" /> + <reference min="0" max="undefined" /> + <outsidereference min="0" max="1" /> + </elements> + </interface> + <interface name="ABX"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="none" /> + <entry name="elementTracker" support="optional" default="on" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="none" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="none" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="optional" default="off" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="2" max="2" /> + <anchor min="0" max="0" /> + <reference min="0" max="0" /> + <outsidereference min="0" max="0" /> + </elements> + </interface> + <interface name="timeline"> + <metrics> + <entry name="testTimer" support="optional" default="on" /> + <entry name="elementTimer" support="optional" default="on" /> + <entry name="elementInitialPosition" support="none" /> + <entry name="elementTracker" support="none" default="off" /> + <entry name="elementFlagListenedTo" support="optional" default="on" /> + <entry name="elementFlagMoved" support="none" /> + <entry name="elementListenTracker" support="optional" default="on" /> + </metrics> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="optional" default="off" /> + <entry name="fragmentFullPlayback" support="optional" default="off" /> + <entry name="fragmentComments" support="optional" default="off" /> + <entry name="scalerange" support="none" /> + </checks> + <show> + <entry name="volume" support="optional" default="off" /> + <entry name="page-count" support="optional" default="off" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="optional" default="off" /> + </show> + <elements> + <number min="1" max="undefined" /> + <anchor min="0" max="0" /> + <reference min="0" max="0" /> + <outsidereference min="0" max="undefined" /> + </elements> + </interface> + </interfaces> + <scaledefinitions> + <scale name="(Blank)"> + </scale> + <scale name="Likert"> + <scalelabel position="0">Strongly Disagree</scalelabel> + <scalelabel position="25">Disagree</scalelabel> + <scalelabel position="50">Neutral</scalelabel> + <scalelabel position="75">Agree</scalelabel> + <scalelabel position="100">Strongly Agree</scalelabel> + </scale> + <scale name="ABC"> + <scalelabel position="100">Imperceptible</scalelabel> + <scalelabel position="75">Perceptible but not annoying</scalelabel> + <scalelabel position="50">Slightly annoying</scalelabel> + <scalelabel position="25">Annoying</scalelabel> + <scalelabel position="0">Very annoying</scalelabel> + </scale> + <scale name="Bipolar"> + <scalelabel position="0">-50</scalelabel> + <scalelabel position="50">0</scalelabel> + <scalelabel position="100">50</scalelabel> + </scale> + <scale name="ACR"> + <scalelabel position="0">Bad</scalelabel> + <scalelabel position="25">Poor</scalelabel> + <scalelabel position="50">Fair</scalelabel> + <scalelabel position="75">Good</scalelabel> + <scalelabel position="100">Excellent</scalelabel> + </scale> + <scale name="DCR"> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scale> + <scale name="CCR"> + <scalelabel position="12">Much Worse</scalelabel> + <scalelabel position="25">Worse</scalelabel> + <scalelabel position="38">Slightly Worse</scalelabel> + <scalelabel position="50">About the same</scalelabel> + <scalelabel position="62">Slightly Better</scalelabel> + <scalelabel position="75">Better</scalelabel> + <scalelabel position="88">Much Better</scalelabel> + </scale> + <scale name="HCRS"> + <scalelabel position="10">Dislike Extremely</scalelabel> + <scalelabel position="20">Dislike Very Much</scalelabel> + <scalelabel position="30">Dislike Moderate</scalelabel> + <scalelabel position="40">Dislike Slightly</scalelabel> + <scalelabel position="50">Neither Like nor Dislike</scalelabel> + <scalelabel position="60">Like Slightly</scalelabel> + <scalelabel position="70">Like Moderate</scalelabel> + <scalelabel position="80">Like Very Much</scalelabel> + <scalelabel position="90">Like Extremely</scalelabel> + </scale> + </scaledefinitions> + <tests> + <test name="APE" interface="APE"> + <descriptions> + <description lang="en">Audio Perceptual Evaluation. A multi-stimulus test where each audio fragment is shown on one continuous slider. Fragments are randomnly positioned along the slider. The user clicks a fragment to play and drags to move.</description> + </descriptions> + </test> + <test name="vertical-sliders" interface="MUSHRA"> + <descriptions> + <description lang="en">Each element is given its own vertical slider with user defined scale markers.</description> + </descriptions> + </test> + <test name="horizontal-sliders" interface="horizontal"> + <descriptions> + <description lang="en">Each element is given its own horizontal slider with user defined scale markers.</description> + </descriptions> + </test> + <test name="discrete" interface="discrete"> + <descriptions> + <description lang="en">Each element is given a horizontal scale broken into a number of discrete choices. The number of choices is defined by the scale markers.</description> + </descriptions> + </test> + <test name="Comparison" interface="AB"> + <descriptions> + <description lang="en">An N-way comparison test. Each element is given its own selector box. The user can select one element per page for submission.</description> + </descriptions> + </test> + <test name="MUSHRA" interface="MUSHRA"> + <descriptions> + <description lang="en">Multi-stimulus with hidden reference and anchor. Each fragment is shown on its own vertical slider. One fragment must be labelled as a reference and another labelled as an anchor. One external reference must also be shown.</description> + </descriptions> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + <entry name="scalerange" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <elements> + <anchor min="1" max="undefined" /> + <reference min="1" max="undefined" /> + <outsidereference min="1" max="1" /> + </elements> + <scale name="ACR" /> + </test> + <test name="Rank" interface="discrete"> + <descriptions> + <description lang="en">Each stimulus is placed on a discrete scale equalling the number of fragments. The fragments are then ranked based on the question posed. Only one element can occupy a rank position</description> + </descriptions> + <checks> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="undefined" /> + </test> + <test name="Likert" interface="discrete"> + <descriptions> + <description lang="en">Each stimulus is placed on a discrete scale. The scale is fixed to the Likert scale options of 'Strongly Disagree', 'Disagree', 'Neutral', 'Agree' and 'Strongly Agree'</description> + </descriptions> + <checks> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="Likert" /> + </test> + <test name="ABC/HR" interface="MUSHRA"> + <descriptions> + <description lang="en">Each stimulus is placed on a vertical slider. The scale is fixed with the labels 'Imperceptible' to 'Very Annoying'</description> + </descriptions> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="ABC" /> + </test> + <test name="Bipolar" interface="horizontal"> + <descriptions> + <description lang="en">Each stimulus is placed on a horizontal slider and initialised to the value '0'. The scale operates from -50 to +5-. In the results this is normalised, like all other interfaces, from 0 (-50) to 1 (+50).</description> + </descriptions> + <checks> + <entry name="fragmentMoved" support="mandatory" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <elements> + <outsidereference min="1" max="1" /> + </elements> + <scale name="Bipolar" /> + </test> + <test name="ACR" interface="discrete"> + <descriptions> + <description lang="en">Absolute Category Rating. Each element is on a discrete scale of 'Bad', 'Poor', 'Fair', 'Good' and 'Excellent'. Each element must be given a rating.</description> + </descriptions> + <checks> + <entry name="fragmentMoved" support="mandatory" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="ACR" /> + </test> + <test name="DCR" interface="discrete"> + <checks> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="DCR" /> + </test> + <test name="CCR" interface="discrete"> + <checks> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <scale name="CCR" /> + </test> + <test name="HCRS" interface="MUSHRA"> + <checks> + <entry name="fragmentMoved" support="mandatory" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <elements> + <outsidereference min="1" max="1" /> + </elements> + <scale name="HCRS" /> + </test> + <test name="ITUR5PCIS" interface="MUSHRA"> + <checks> + <entry name="fragmentMoved" support="none" /> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <elements> + <outsidereference min="1" max="1" /> + </elements> + <scale name="ABC" /> + </test> + <test name="AB" interface="AB"> + <descriptions> + <description lang="en">Each page has only two audio fragments. The user must select one of the two fragments to proceed. There can be one hidden reference.</description> + </descriptions> + <checks> + <entry name="fragmentPlayed" support="none" /> + <entry name="fragmentFullPlayback" support="none" /> + <entry name="fragmentComments" support="none" /> + </checks> + <show> + <entry name="volume" support="none" /> + <entry name="page-count" support="none" /> + <entry name="playhead" support="none" /> + <entry name="comments" support="none" /> + </show> + <elements> + <number min="2" max="2" /> + <outsidereference min="0" max="1" /> + </elements> + </test> + <test name="ABX" interface="ABX"> + <descriptions> + <description lang="en">Each page has two audio fragments presented as A and B. The test duplicates one of the fragments and presents it as X. The user must choose which, out of A or B, is closest to X.</description> + </descriptions> + </test> + <test name="timeline" interface="timeline"> + <descriptions> + <description lang="en">Each fragment is displayed with a clickable waveform of itself. The user must click on the waveform at the location that a specific event occured. Users can then enter in information about this event. This test is unit-/value-less.</description> + </descriptions> + </test> + </tests> + </root>
--- a/test_create/style.css Mon Nov 14 12:11:38 2016 +0000 +++ b/test_create/style.css Mon Nov 14 14:17:03 2016 +0000 @@ -1,30 +1,27 @@ div#blanket { z-index: 2; - background-color: rgba(0,0,0,0.5); + background-color: rgba(0, 0, 0, 0.5); width: 100%; height: 100%; position: fixed; left: 0px; top: 0px; } - div#popupHolder { z-index: 3; - background-color: rgba(255,255,255,1); + background-color: rgba(255, 255, 255, 1); width: 730px; height: 480px; position: fixed; border-radius: 10px; - box-shadow: 0px 0px 50px #000; + box-shadow: 0px 0px 50px #000; padding: 10px; } - div#popup-title-holder { width: 100%; height: 50px; font-size: 2em; } - button.popup-button { width: 60px; height: 27px; @@ -32,15 +29,12 @@ position: absolute; bottom: 10px; } - button#popup-proceed { right: 10px; } - button#popup-back { left: 10px; } - div.drag-area { border: 3px black dashed; } @@ -53,40 +47,30 @@ div.drag-error { background-color: coral } - div#project-drop { width: 99%; height: 50px; margin: 10px 0px; } - div.popup-checkbox { padding: 5px; } - div.popup-checkbox input { margin: 0px 5px; } - div.popup-option-entry { padding: 5px 0px; border-bottom: 1px solid; } - -div.disabled{ - color: rgb(100,100,100); +div.disabled { + color: rgb(100, 100, 100); } - - -div#page-holder > div.node{ - background-color: rgb(200,228,151); +div#page-holder > div.node { + background-color: rgb(200, 228, 151); } - -div#content > div#setup{ +div#content > div#setup { background-color: coral; } - - div.node { float: left; padding: 10px; @@ -94,7 +78,7 @@ border-radius: 10px; margin: 10px; min-width: 92%; - background-color: rgba(255,255,255,0.5); + background-color: rgba(255, 255, 255, 0.5); } div.node-title { float: left; @@ -127,13 +111,13 @@ div.attribute input[type=number] { width: 80px; } -div.attribute input[type=radio], div.attribute input[type=checkbox]{ +div.attribute input[type=radio], +div.attribute input[type=checkbox] { width: 10px; } -input:disabled+label{ +input:disabled+label { text-decoration: line-through; } - div.survey-entry-attribute { margin: 10px 0px; border: 1px gray solid; @@ -142,7 +126,6 @@ line-height: 40px; padding: 0px 10px; } - -div.survey-entry-attribute span{ +div.survey-entry-attribute span { margin-right: 10px; -} \ No newline at end of file +}
--- a/tests/examples/AB_example.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/AB_example.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,97 +1,97 @@ <?xml version="1.0" encoding="utf-8"?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" playOne="true"> - <survey location="before"> - <surveyentry type="question" id="sessionId" mandatory="true"> - <statement>Please enter your name.</statement> - </surveyentry> - <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> - <statement>Please select with which activities you have any experience (example checkbox question)</statement> - <option name="musician">Playing a musical instrument</option> - <option name="soundengineer">Recording or mixing audio</option> - <option name="developer">Developing audio software</option> - <option name="hwdesigner">Designing or building audio hardware</option> - <option name="researcher">Research in the field of audio</option> - </surveyentry> - <surveyentry type="statement" id="test-intro"> - <statement>This is an example of an 'AB'-style test, with two pages, using the test stimuli in 'example_eval/'. The 'playOne' configuration option means a fragment has to be finished playing before another fragment can be auditioned. </statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="location" mandatory="true" boxsize="large"> - <statement>Please enter your location. (example mandatory text question)</statement> - </surveyentry> - <surveyentry type="number" id="age" min="0"> - <statement>Please enter your age (example non-mandatory number question)</statement> - </surveyentry> - <surveyentry type="radio" id="rating"> - <statement>Please rate this interface (example radio button question)</statement> - <option name="bad">Bad</option> - <option name="poor">Poor</option> - <option name="good">Good</option> - <option name="great">Great</option> - </surveyentry> - <surveyentry type="statement" id="test-thank-you"> - <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> - </surveyentry> - </survey> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name='volume'/> - <interfaceoption type="show" name='comments'/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' loudness="-12"> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface> - <title>Depth</title> - </interface> - <audioelement url="0.wav" id="track-0"/> - <audioelement url="1.wav" id="track-1"/> - <survey location="before"> - <surveyentry type="statement" id="test-0-intro"> - <statement>A two way comparison using randomised element order, automatic loudness and synchronised looping.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-0" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> - <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' loudness="-12"> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface> - <title>Depth</title> - </interface> - <audioelement url="0.wav" id="track-2"/> - <audioelement url="1.wav" id="track-3"/> - <audioelement url="2.wav" id="track-4"/> - <audioelement url="3.wav" id="track-5"/> - <audioelement url="4.wav" id="track-6"/> - <audioelement url="5.wav" id="track-7"/> - <audioelement url="6.wav" id="track-8"/> - <survey location="before"> - <surveyentry type="statement" id="test-1-intro"> - <statement>A 7 way comparison using randomised element order and synchronised looping.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-1" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> -</waet> \ No newline at end of file + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="AB" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" playOne="true"> + <survey location="before"> + <surveyentry type="question" id="sessionId" mandatory="true"> + <statement>Please enter your name.</statement> + </surveyentry> + <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> + <statement>Please select with which activities you have any experience (example checkbox question)</statement> + <option name="musician">Playing a musical instrument</option> + <option name="soundengineer">Recording or mixing audio</option> + <option name="developer">Developing audio software</option> + <option name="hwdesigner">Designing or building audio hardware</option> + <option name="researcher">Research in the field of audio</option> + </surveyentry> + <surveyentry type="statement" id="test-intro"> + <statement>This is an example of an 'AB'-style test, with two pages, using the test stimuli in 'example_eval/'. The 'playOne' configuration option means a fragment has to be finished playing before another fragment can be auditioned. </statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="location" mandatory="true" boxsize="large"> + <statement>Please enter your location. (example mandatory text question)</statement> + </surveyentry> + <surveyentry type="number" id="age" min="0"> + <statement>Please enter your age (example non-mandatory number question)</statement> + </surveyentry> + <surveyentry type="radio" id="rating"> + <statement>Please rate this interface (example radio button question)</statement> + <option name="bad">Bad</option> + <option name="poor">Poor</option> + <option name="good">Good</option> + <option name="great">Great</option> + </surveyentry> + <surveyentry type="statement" id="test-thank-you"> + <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> + </surveyentry> + </survey> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name='volume' /> + <interfaceoption type="show" name='comments' /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' loudness="-12"> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface> + <title>Depth</title> + </interface> + <audioelement url="0.wav" id="track-0" /> + <audioelement url="1.wav" id="track-1" /> + <survey location="before"> + <surveyentry type="statement" id="test-0-intro"> + <statement>A two way comparison using randomised element order, automatic loudness and synchronised looping.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-0" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' loudness="-12"> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface> + <title>Depth</title> + </interface> + <audioelement url="0.wav" id="track-2" /> + <audioelement url="1.wav" id="track-3" /> + <audioelement url="2.wav" id="track-4" /> + <audioelement url="3.wav" id="track-5" /> + <audioelement url="4.wav" id="track-6" /> + <audioelement url="5.wav" id="track-7" /> + <audioelement url="6.wav" id="track-8" /> + <survey location="before"> + <surveyentry type="statement" id="test-1-intro"> + <statement>A 7 way comparison using randomised element order and synchronised looping.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-1" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + </waet>
--- a/tests/examples/APE_example.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/APE_example.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,143 +1,143 @@ <?xml version="1.0" encoding="utf-8"?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="APE" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" calibration="true"> - <survey location="before"> - <surveyentry type="question" id="sessionId" mandatory="true"> - <statement>Please enter your name.</statement> - <conditional check="equals" value="John" jumpToOnPass="test-intro" jumpToOnFail="checkboxtest"/> - </surveyentry> - <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> - <statement>Please select with which activities you have any experience (example checkbox question)</statement> - <option name="musician">Playing a musical instrument</option> - <option name="soundengineer">Recording or mixing audio</option> - <option name="developer">Developing audio software</option> - <option name="hwdesigner">Designing or building audio hardware</option> - <option name="researcher">Research in the field of audio</option> - </surveyentry> - <surveyentry type="question" id="instrument" mandatory="false"> - <statement>What instrument did you play</statement> - </surveyentry> - <surveyentry type="statement" id="test-intro"> - <statement>This is an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="location" mandatory="true" boxsize="large"> - <statement>Please enter your location. (example mandatory text question)</statement> - </surveyentry> - <surveyentry type="number" id="age" min="0"> - <statement>Please enter your age (example non-mandatory number question)</statement> - </surveyentry> - <surveyentry type="radio" id="rating"> - <statement>Please rate this interface (example radio button question)</statement> - <option name="bad">Bad</option> - <option name="poor">Poor</option> - <option name="good">Good</option> - <option name="great">Great</option> - </surveyentry> - <surveyentry type="statement" id="thankyou"> - <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> - </surveyentry> - </survey> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - <interfaceoption type="check" name="fragmentPlayed"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name="comments"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface name="preference"> - <title>Preference</title> - <scales> - <scalelabel position="0">Min</scalelabel> - <scalelabel position="100">Max</scalelabel> - <scalelabel position="50">Middle</scalelabel> - <scalelabel position="20">20</scalelabel> - </scales> - </interface> - <interface name="depth"> - <title>Depth</title> - <scales> - <scalelabel position="0">Low</scalelabel> - <scalelabel position="100">High</scalelabel> - <scalelabel position="50">Middle</scalelabel> - <scalelabel position="50">Middle</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-0" type="anchor"/> - <audioelement url="1.wav" id="track-1"/> - <audioelement url="2.wav" id="track-2"/> - <audioelement url="3.wav" id="track-3"/> - <audioelement url="4.wav" id="track-4"/> - <survey location="before"> - <surveyentry type="statement" id="test-0-intro"> - <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-0" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> - <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' label="letter"> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface name="preference"> - <title>Example Test Question</title> - <scales> - <scalelabel position="0">Min</scalelabel> - <scalelabel position="100">Max</scalelabel> - <scalelabel position="50">Middle</scalelabel> - <scalelabel position="20">20</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" gain="-6" id="track-5" type="anchor" marker="20"/> - <audioelement url="1.wav" gain="0.0" id="track-6" type="reference" marker="80"/> - <audioelement url="2.wav" gain="0.0" id="track-7"/> - <audioelement url="3.wav" gain="0.0" id="track-8"/> - <audioelement url="4.wav" gain="0.0" id="track-9"/> - <audioelement url="5.wav" gain="0.0" id="track-10"/> - <audioelement url="6.wav" gain="0.0" id="track-11" type="outside-reference"/> - <commentquestion id='mixingExperience' type="question"> - <statement>What is your general experience with numbers?</statement> - </commentquestion> - <commentquestion id="preference" type="radio"> - <statement>Please enter your overall preference</statement> - <option name="worst">Very Bad</option> - <option name="bad"></option> - <option name="OK">OK</option> - <option name="Good"></option> - <option name="Great">Great</option> - </commentquestion> - <commentquestion id="character" type="checkbox"> - <statement>Please describe the overall character</statement> - <option name="funky">Funky</option> - <option name="mellow">Mellow</option> - <option name="laidback">Laid back</option> - <option name="heavy">Heavy</option> - </commentquestion> - <survey location="before"> - <surveyentry type="statement" id="test-1-intro"> - <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-1" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> -</waet> \ No newline at end of file + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="APE" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23" calibration="true"> + <survey location="before"> + <surveyentry type="question" id="sessionId" mandatory="true"> + <statement>Please enter your name.</statement> + <conditional check="equals" value="John" jumpToOnPass="test-intro" jumpToOnFail="checkboxtest" /> + </surveyentry> + <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> + <statement>Please select with which activities you have any experience (example checkbox question)</statement> + <option name="musician">Playing a musical instrument</option> + <option name="soundengineer">Recording or mixing audio</option> + <option name="developer">Developing audio software</option> + <option name="hwdesigner">Designing or building audio hardware</option> + <option name="researcher">Research in the field of audio</option> + </surveyentry> + <surveyentry type="question" id="instrument" mandatory="false"> + <statement>What instrument did you play</statement> + </surveyentry> + <surveyentry type="statement" id="test-intro"> + <statement>This is an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="location" mandatory="true" boxsize="large"> + <statement>Please enter your location. (example mandatory text question)</statement> + </surveyentry> + <surveyentry type="number" id="age" min="0"> + <statement>Please enter your age (example non-mandatory number question)</statement> + </surveyentry> + <surveyentry type="radio" id="rating"> + <statement>Please rate this interface (example radio button question)</statement> + <option name="bad">Bad</option> + <option name="poor">Poor</option> + <option name="good">Good</option> + <option name="great">Great</option> + </surveyentry> + <surveyentry type="statement" id="thankyou"> + <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> + </surveyentry> + </survey> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + <interfaceoption type="check" name="fragmentPlayed" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name="comments" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface name="preference"> + <title>Preference</title> + <scales> + <scalelabel position="0">Min</scalelabel> + <scalelabel position="100">Max</scalelabel> + <scalelabel position="50">Middle</scalelabel> + <scalelabel position="20">20</scalelabel> + </scales> + </interface> + <interface name="depth"> + <title>Depth</title> + <scales> + <scalelabel position="0">Low</scalelabel> + <scalelabel position="100">High</scalelabel> + <scalelabel position="50">Middle</scalelabel> + <scalelabel position="50">Middle</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-0" type="anchor" /> + <audioelement url="1.wav" id="track-1" /> + <audioelement url="2.wav" id="track-2" /> + <audioelement url="3.wav" id="track-3" /> + <audioelement url="4.wav" id="track-4" /> + <survey location="before"> + <surveyentry type="statement" id="test-0-intro"> + <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-0" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false' label="letter"> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface name="preference"> + <title>Example Test Question</title> + <scales> + <scalelabel position="0">Min</scalelabel> + <scalelabel position="100">Max</scalelabel> + <scalelabel position="50">Middle</scalelabel> + <scalelabel position="20">20</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" gain="-6" id="track-5" type="anchor" marker="20" /> + <audioelement url="1.wav" gain="0.0" id="track-6" type="reference" marker="80" /> + <audioelement url="2.wav" gain="0.0" id="track-7" /> + <audioelement url="3.wav" gain="0.0" id="track-8" /> + <audioelement url="4.wav" gain="0.0" id="track-9" /> + <audioelement url="5.wav" gain="0.0" id="track-10" /> + <audioelement url="6.wav" gain="0.0" id="track-11" type="outside-reference" /> + <commentquestion id='mixingExperience' type="question"> + <statement>What is your general experience with numbers?</statement> + </commentquestion> + <commentquestion id="preference" type="radio"> + <statement>Please enter your overall preference</statement> + <option name="worst">Very Bad</option> + <option name="bad"></option> + <option name="OK">OK</option> + <option name="Good"></option> + <option name="Great">Great</option> + </commentquestion> + <commentquestion id="character" type="checkbox"> + <statement>Please describe the overall character</statement> + <option name="funky">Funky</option> + <option name="mellow">Mellow</option> + <option name="laidback">Laid back</option> + <option name="heavy">Heavy</option> + </commentquestion> + <survey location="before"> + <surveyentry type="statement" id="test-1-intro"> + <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-1" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + </waet>
--- a/tests/examples/horizontal_example.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/horizontal_example.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,33 +1,33 @@ <?xml version="1.0" encoding="UTF-8" ?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="ABC" projectReturn="save.php"> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name="volume"/> - <interfaceoption type="show" name="comments"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> - <interface> - <scales> - <scalelabel position="0">-50</scalelabel> - <scalelabel position="50">0</scalelabel> - <scalelabel position="100">50</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-1"/> - <audioelement url="1.wav" id="track-2"/> - </page> -</waet> + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="ABC" projectReturn="save.php"> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name="volume" /> + <interfaceoption type="show" name="comments" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> + <interface> + <scales> + <scalelabel position="0">-50</scalelabel> + <scalelabel position="50">0</scalelabel> + <scalelabel position="100">50</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-1" /> + <audioelement url="1.wav" id="track-2" /> + </page> + </waet>
--- a/tests/examples/mushra_example.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/mushra_example.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,133 +1,133 @@ <?xml version="1.0" encoding="utf-8"?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="MUSHRA" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23"> - <exitText>Thank you for looking at WAET. You can modify the successful completion text as well!</exitText> - <survey location="before"> - <surveyentry type="question" id="sessionId" mandatory="true"> - <statement>Please enter your name.</statement> - </surveyentry> - <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> - <statement>Please select with which activities you have any experience (example checkbox question)</statement> - <option name="musician">Playing a musical instrument</option> - <option name="soundengineer">Recording or mixing audio</option> - <option name="developer">Developing audio software</option> - <option name="hwdesigner">Designing or building audio hardware</option> - <option name="researcher">Research in the field of audio</option> - </surveyentry> - <surveyentry type="statement" id="test-intro"> - <statement>This is an example of an 'MUSHRA'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="location" mandatory="true" boxsize="large"> - <statement>Please enter your location. (example mandatory text question)</statement> - </surveyentry> - <surveyentry type="number" id="age" min="0"> - <statement>Please enter your age (example non-mandatory number question)</statement> - </surveyentry> - <surveyentry type="radio" id="rating"> - <statement>Please rate this interface (example radio button question)</statement> - <option name="bad">Bad</option> - <option name="poor">Poor</option> - <option name="good">Good</option> - <option name="great">Great</option> - </surveyentry> - <surveyentry type="statement" id="thankyou"> - <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> - </surveyentry> - </survey> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name="volume"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface> - <scales> - <scalelabel position="12">Much Worse</scalelabel> - <scalelabel position="25">Worse</scalelabel> - <scalelabel position="38">Slightly Worse</scalelabel> - <scalelabel position="50">About the same</scalelabel> - <scalelabel position="62">Slightly Better</scalelabel> - <scalelabel position="75">Better</scalelabel> - <scalelabel position="88">Much Better</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-0" type="anchor"/> - <audioelement url="1.wav" id="track-1"/> - <audioelement url="2.wav" id="track-2"/> - <audioelement url="3.wav" id="track-3"/> - <audioelement url="4.wav" id="track-4"/> - <survey location="before"> - <surveyentry type="statement" id="test-0-intro"> - <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75% using a Comparison Category Rating Scale.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-0" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> - <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false'> - <commentboxprefix>Comment on fragment</commentboxprefix> - <interface name="preference"> - <title>Example Test Question</title> - <interfaceoption type="show" name="comments"/> - <scales> - <scalelabel position="0">Min</scalelabel> - <scalelabel position="100">Max</scalelabel> - <scalelabel position="50">Middle</scalelabel> - <scalelabel position="20">20</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" gain="-6.0" id="track-5" type="anchor" marker="20"/> - <audioelement url="1.wav" gain="0.0" id="track-6" type="reference" marker="80"/> - <audioelement url="2.wav" gain="0.0" id="track-7"/> - <audioelement url="3.wav" gain="0.0" id="track-8"/> - <audioelement url="4.wav" gain="0.0" id="track-9"/> - <audioelement url="5.wav" gain="0.0" id="track-10"/> - <audioelement url="1.wav" gain="0.0" id="track-11" type="outside-reference"/> - <commentquestion id='mixingExperience' type="question"> - <statement>What is your general experience with numbers?</statement> - </commentquestion> - <commentquestion id="preference" type="radio"> - <statement>Please enter your overall preference</statement> - <option name="worst">Very Bad</option> - <option name="bad"></option> - <option name="OK">OK</option> - <option name="Good"></option> - <option name="Great">Great</option> - </commentquestion> - <commentquestion id="character" type="checkbox"> - <statement>Please describe the overall character</statement> - <option name="funky">Funky</option> - <option name="mellow">Mellow</option> - <option name="laidback">Laid back</option> - <option name="heavy">Heavy</option> - </commentquestion> - <survey location="before"> - <surveyentry type="statement" id="test-1-intro"> - <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> - </surveyentry> - </survey> - <survey location="after"> - <surveyentry type="question" id="genre-1" mandatory="true"> - <statement>Please enter the genre.</statement> - </surveyentry> - </survey> - </page> -</waet> \ No newline at end of file + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="MUSHRA" projectReturn="save.php" randomiseOrder='true' poolSize="2" loudness="-23"> + <exitText>Thank you for looking at WAET. You can modify the successful completion text as well!</exitText> + <survey location="before"> + <surveyentry type="question" id="sessionId" mandatory="true"> + <statement>Please enter your name.</statement> + </surveyentry> + <surveyentry type="checkbox" id="checkboxtest" mandatory="true"> + <statement>Please select with which activities you have any experience (example checkbox question)</statement> + <option name="musician">Playing a musical instrument</option> + <option name="soundengineer">Recording or mixing audio</option> + <option name="developer">Developing audio software</option> + <option name="hwdesigner">Designing or building audio hardware</option> + <option name="researcher">Research in the field of audio</option> + </surveyentry> + <surveyentry type="statement" id="test-intro"> + <statement>This is an example of an 'MUSHRA'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="location" mandatory="true" boxsize="large"> + <statement>Please enter your location. (example mandatory text question)</statement> + </surveyentry> + <surveyentry type="number" id="age" min="0"> + <statement>Please enter your age (example non-mandatory number question)</statement> + </surveyentry> + <surveyentry type="radio" id="rating"> + <statement>Please rate this interface (example radio button question)</statement> + <option name="bad">Bad</option> + <option name="poor">Poor</option> + <option name="good">Good</option> + <option name="great">Great</option> + </surveyentry> + <surveyentry type="statement" id="thankyou"> + <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> + </surveyentry> + </survey> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name="volume" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='true' loudness="-12"> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface> + <scales> + <scalelabel position="12">Much Worse</scalelabel> + <scalelabel position="25">Worse</scalelabel> + <scalelabel position="38">Slightly Worse</scalelabel> + <scalelabel position="50">About the same</scalelabel> + <scalelabel position="62">Slightly Better</scalelabel> + <scalelabel position="75">Better</scalelabel> + <scalelabel position="88">Much Better</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-0" type="anchor" /> + <audioelement url="1.wav" id="track-1" /> + <audioelement url="2.wav" id="track-2" /> + <audioelement url="3.wav" id="track-3" /> + <audioelement url="4.wav" id="track-4" /> + <survey location="before"> + <surveyentry type="statement" id="test-0-intro"> + <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75% using a Comparison Category Rating Scale.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-0" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='0' loop='false'> + <commentboxprefix>Comment on fragment</commentboxprefix> + <interface name="preference"> + <title>Example Test Question</title> + <interfaceoption type="show" name="comments" /> + <scales> + <scalelabel position="0">Min</scalelabel> + <scalelabel position="100">Max</scalelabel> + <scalelabel position="50">Middle</scalelabel> + <scalelabel position="20">20</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" gain="-6.0" id="track-5" type="anchor" marker="20" /> + <audioelement url="1.wav" gain="0.0" id="track-6" type="reference" marker="80" /> + <audioelement url="2.wav" gain="0.0" id="track-7" /> + <audioelement url="3.wav" gain="0.0" id="track-8" /> + <audioelement url="4.wav" gain="0.0" id="track-9" /> + <audioelement url="5.wav" gain="0.0" id="track-10" /> + <audioelement url="1.wav" gain="0.0" id="track-11" type="outside-reference" /> + <commentquestion id='mixingExperience' type="question"> + <statement>What is your general experience with numbers?</statement> + </commentquestion> + <commentquestion id="preference" type="radio"> + <statement>Please enter your overall preference</statement> + <option name="worst">Very Bad</option> + <option name="bad"></option> + <option name="OK">OK</option> + <option name="Good"></option> + <option name="Great">Great</option> + </commentquestion> + <commentquestion id="character" type="checkbox"> + <statement>Please describe the overall character</statement> + <option name="funky">Funky</option> + <option name="mellow">Mellow</option> + <option name="laidback">Laid back</option> + <option name="heavy">Heavy</option> + </commentquestion> + <survey location="before"> + <surveyentry type="statement" id="test-1-intro"> + <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> + </surveyentry> + </survey> + <survey location="after"> + <surveyentry type="question" id="genre-1" mandatory="true"> + <statement>Please enter the genre.</statement> + </surveyentry> + </survey> + </page> + </waet>
--- a/tests/examples/radio_example.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/radio_example.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,37 +1,37 @@ <?xml version="1.0" encoding="UTF-8" ?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="likert" projectReturn="save.php" crossFade="3.0"> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentMoved"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name="volume"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name="comments"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-1" alwaysInclude="true"/> - <audioelement url="1.wav" id="track-2"/> - <audioelement url="3.wav" id="track-4"/> - <audioelement url="3.wav" id="track-5"/> - </page> -</waet> + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="likert" projectReturn="save.php" crossFade="3.0"> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentMoved" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name="volume" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name="comments" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-1" alwaysInclude="true" /> + <audioelement url="1.wav" id="track-2" /> + <audioelement url="3.wav" id="track-4" /> + <audioelement url="3.wav" id="track-5" /> + </page> + </waet>
--- a/tests/examples/timeline.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/tests/examples/timeline.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,80 +1,80 @@ <?xml version="1.0" encoding="UTF-8" ?> -<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> - <setup interface="timeline" projectReturn="save.php"> - <metric> - <metricenable>testTimer</metricenable> - <metricenable>elementTimer</metricenable> - <metricenable>elementInitialPosition</metricenable> - <metricenable>elementTracker</metricenable> - <metricenable>elementFlagListenedTo</metricenable> - <metricenable>elementFlagMoved</metricenable> - <metricenable>elementListenTracker</metricenable> - </metric> - <interface> - <interfaceoption type="check" name="fragmentPlayed"/> - <interfaceoption type="check" name="scalerange" min="25" max="75"/> - <interfaceoption type="show" name="volume"/> - <interfaceoption type="show" name='playhead'/> - <interfaceoption type="show" name="page-count"/> - <interfaceoption type="show" name="comments"/> - </interface> - </setup> - <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> - <title>My Test</title> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-1"/> - <audioelement url="1.wav" id="track-2"/> - <commentquestion id="preference" type="radio"> - <statement>Please enter your overall preference</statement> - <option name="worst">Very Bad</option> - <option name="bad"></option> - <option name="OK">OK</option> - <option name="Good"></option> - <option name="Great">Great</option> - </commentquestion> - <commentquestion id="character" type="checkbox"> - <statement>Please describe the overall character</statement> - <option name="funky">Funky</option> - <option name="mellow">Mellow</option> - <option name="laidback">Laid back</option> - <option name="heavy">Heavy</option> - </commentquestion> - </page> - <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> - <title>My Test</title> - <interface> - <scales> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scales> - </interface> - <audioelement url="0.wav" id="track-3"/> - <audioelement url="1.wav" id="track-4"/> - <commentquestion id="preference1" type="radio"> - <statement>Please enter your overall preference</statement> - <option name="worst">Very Bad</option> - <option name="bad"></option> - <option name="OK">OK</option> - <option name="Good"></option> - <option name="Great">Great</option> - </commentquestion> - <commentquestion id="character1" type="checkbox"> - <statement>Please describe the overall character</statement> - <option name="funky">Funky</option> - <option name="mellow">Mellow</option> - <option name="laidback">Laid back</option> - <option name="heavy">Heavy</option> - </commentquestion> - </page> -</waet> + <waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd"> + <setup interface="timeline" projectReturn="save.php"> + <metric> + <metricenable>testTimer</metricenable> + <metricenable>elementTimer</metricenable> + <metricenable>elementInitialPosition</metricenable> + <metricenable>elementTracker</metricenable> + <metricenable>elementFlagListenedTo</metricenable> + <metricenable>elementFlagMoved</metricenable> + <metricenable>elementListenTracker</metricenable> + </metric> + <interface> + <interfaceoption type="check" name="fragmentPlayed" /> + <interfaceoption type="check" name="scalerange" min="25" max="75" /> + <interfaceoption type="show" name="volume" /> + <interfaceoption type="show" name='playhead' /> + <interfaceoption type="show" name="page-count" /> + <interfaceoption type="show" name="comments" /> + </interface> + </setup> + <page id='test-0' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <title>My Test</title> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-1" /> + <audioelement url="1.wav" id="track-2" /> + <commentquestion id="preference" type="radio"> + <statement>Please enter your overall preference</statement> + <option name="worst">Very Bad</option> + <option name="bad"></option> + <option name="OK">OK</option> + <option name="Good"></option> + <option name="Great">Great</option> + </commentquestion> + <commentquestion id="character" type="checkbox"> + <statement>Please describe the overall character</statement> + <option name="funky">Funky</option> + <option name="mellow">Mellow</option> + <option name="laidback">Laid back</option> + <option name="heavy">Heavy</option> + </commentquestion> + </page> + <page id='test-1' hostURL="media/example/" randomiseOrder='true' repeatCount='4' loop='true' loudness="-23"> + <title>My Test</title> + <interface> + <scales> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scales> + </interface> + <audioelement url="0.wav" id="track-3" /> + <audioelement url="1.wav" id="track-4" /> + <commentquestion id="preference1" type="radio"> + <statement>Please enter your overall preference</statement> + <option name="worst">Very Bad</option> + <option name="bad"></option> + <option name="OK">OK</option> + <option name="Good"></option> + <option name="Great">Great</option> + </commentquestion> + <commentquestion id="character1" type="checkbox"> + <statement>Please describe the overall character</statement> + <option name="funky">Funky</option> + <option name="mellow">Mellow</option> + <option name="laidback">Laid back</option> + <option name="heavy">Heavy</option> + </commentquestion> + </page> + </waet>
--- a/xml/scaledefinitions.xml Mon Nov 14 12:11:38 2016 +0000 +++ b/xml/scaledefinitions.xml Mon Nov 14 14:17:03 2016 +0000 @@ -1,56 +1,56 @@ <?xml version="1.0" encoding="UTF-8" ?> -<scaledefinitions> - <scale name="Likert"> - <scalelabel position="0">Strongly Disagree</scalelabel> - <scalelabel position="25">Disagree</scalelabel> - <scalelabel position="50">Neutral</scalelabel> - <scalelabel position="75">Agree</scalelabel> - <scalelabel position="100">Strongly Agree</scalelabel> - </scale> - <scale name="ABC"> - <scalelabel position="100">Imperceptible</scalelabel> - <scalelabel position="75">Perceptible but not annoying</scalelabel> - <scalelabel position="50">Slightly annoying</scalelabel> - <scalelabel position="25">Annoying</scalelabel> - <scalelabel position="0">Very annoying</scalelabel> - </scale> - <scale name="Bipolar"> - <scalelabel position="0">-50</scalelabel> - <scalelabel position="50">0</scalelabel> - <scalelabel position="100">50</scalelabel> - </scale> - <scale name="ACR"> - <scalelabel position="0">Bad</scalelabel> - <scalelabel position="25">Poor</scalelabel> - <scalelabel position="50">Fair</scalelabel> - <scalelabel position="75">Good</scalelabel> - <scalelabel position="100">Excellent</scalelabel> - </scale> - <scale name="DCR"> - <scalelabel position="0">(1) Very Annoying</scalelabel> - <scalelabel position="25">(2) Annoying</scalelabel> - <scalelabel position="50">(3) Slightly Annoying</scalelabel> - <scalelabel position="75">(4) Audible but not Annoying</scalelabel> - <scalelabel position="100">(5) Inaudible</scalelabel> - </scale> - <scale name="CCR"> - <scalelabel position="12">Much Worse</scalelabel> - <scalelabel position="25">Worse</scalelabel> - <scalelabel position="38">Slightly Worse</scalelabel> - <scalelabel position="50">About the same</scalelabel> - <scalelabel position="62">Slightly Better</scalelabel> - <scalelabel position="75">Better</scalelabel> - <scalelabel position="88">Much Better</scalelabel> - </scale> - <scale name="Hedonic Category Rating Scale"> - <scalelabel position="10">Dislike Extremely</scalelabel> - <scalelabel position="20">Dislike Very Much</scalelabel> - <scalelabel position="30">Dislike Moderate</scalelabel> - <scalelabel position="40">Dislike Slightly</scalelabel> - <scalelabel position="50">Neither Like nor Dislike</scalelabel> - <scalelabel position="60">Like Slightly</scalelabel> - <scalelabel position="70">Like Moderate</scalelabel> - <scalelabel position="80">Like Very Much</scalelabel> - <scalelabel position="90">Like Extremely</scalelabel> - </scale> -</scaledefinitions> + <scaledefinitions> + <scale name="Likert"> + <scalelabel position="0">Strongly Disagree</scalelabel> + <scalelabel position="25">Disagree</scalelabel> + <scalelabel position="50">Neutral</scalelabel> + <scalelabel position="75">Agree</scalelabel> + <scalelabel position="100">Strongly Agree</scalelabel> + </scale> + <scale name="ABC"> + <scalelabel position="100">Imperceptible</scalelabel> + <scalelabel position="75">Perceptible but not annoying</scalelabel> + <scalelabel position="50">Slightly annoying</scalelabel> + <scalelabel position="25">Annoying</scalelabel> + <scalelabel position="0">Very annoying</scalelabel> + </scale> + <scale name="Bipolar"> + <scalelabel position="0">-50</scalelabel> + <scalelabel position="50">0</scalelabel> + <scalelabel position="100">50</scalelabel> + </scale> + <scale name="ACR"> + <scalelabel position="0">Bad</scalelabel> + <scalelabel position="25">Poor</scalelabel> + <scalelabel position="50">Fair</scalelabel> + <scalelabel position="75">Good</scalelabel> + <scalelabel position="100">Excellent</scalelabel> + </scale> + <scale name="DCR"> + <scalelabel position="0">(1) Very Annoying</scalelabel> + <scalelabel position="25">(2) Annoying</scalelabel> + <scalelabel position="50">(3) Slightly Annoying</scalelabel> + <scalelabel position="75">(4) Audible but not Annoying</scalelabel> + <scalelabel position="100">(5) Inaudible</scalelabel> + </scale> + <scale name="CCR"> + <scalelabel position="12">Much Worse</scalelabel> + <scalelabel position="25">Worse</scalelabel> + <scalelabel position="38">Slightly Worse</scalelabel> + <scalelabel position="50">About the same</scalelabel> + <scalelabel position="62">Slightly Better</scalelabel> + <scalelabel position="75">Better</scalelabel> + <scalelabel position="88">Much Better</scalelabel> + </scale> + <scale name="Hedonic Category Rating Scale"> + <scalelabel position="10">Dislike Extremely</scalelabel> + <scalelabel position="20">Dislike Very Much</scalelabel> + <scalelabel position="30">Dislike Moderate</scalelabel> + <scalelabel position="40">Dislike Slightly</scalelabel> + <scalelabel position="50">Neither Like nor Dislike</scalelabel> + <scalelabel position="60">Like Slightly</scalelabel> + <scalelabel position="70">Like Moderate</scalelabel> + <scalelabel position="80">Like Very Much</scalelabel> + <scalelabel position="90">Like Extremely</scalelabel> + </scale> + </scaledefinitions>
--- a/xml/test-schema.xsd Mon Nov 14 12:11:38 2016 +0000 +++ b/xml/test-schema.xsd Mon Nov 14 14:17:03 2016 +0000 @@ -26,8 +26,8 @@ </xs:restriction> </xs:simpleType> </xs:attribute> - - <xs:attribute name="playOne" type="xs:boolean" default="false"/> + + <xs:attribute name="playOne" type="xs:boolean" default="false" /> <!-- define complex elements--> <xs:element name="waet"> @@ -254,16 +254,16 @@ <xs:attribute name="check" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> - <xs:enumeration value="equals"/> - <xs:enumeration value="lessThan"/> - <xs:enumeration value="greaterThan"/> - <xs:enumeration value="stringContains"/> + <xs:enumeration value="equals" /> + <xs:enumeration value="lessThan" /> + <xs:enumeration value="greaterThan" /> + <xs:enumeration value="stringContains" /> </xs:restriction> </xs:simpleType> </xs:attribute> - <xs:attribute name="value" type="xs:string" use="optional"/> - <xs:attribute name="jumpToOnPass" type="xs:string" use="optional"/> - <xs:attribute name="jumpToOnFail" type="xs:string" use="optional"/> + <xs:attribute name="value" type="xs:string" use="optional" /> + <xs:attribute name="jumpToOnPass" type="xs:string" use="optional" /> + <xs:attribute name="jumpToOnFail" type="xs:string" use="optional" /> </xs:complexType> </xs:element> </xs:sequence> @@ -295,7 +295,7 @@ </xs:restriction> </xs:simpleType> </xs:attribute> - <xs:attribute name="url" type="xs:string" use="optional"/> + <xs:attribute name="url" type="xs:string" use="optional" /> </xs:complexType> </xs:element> </xs:sequence>