# HG changeset patch # User Nicholas Jillings # Date 1459427502 -3600 # Node ID 6c819878ac8542780832670ad80305305232ce59 # Parent b24d861c96b3168b80f9475427bdd780a7bd4e4a Major updates. Specification Nodes now own file (specification.js). Updating Analysis to allow filtering based on survey responses. diff -r b24d861c96b3 -r 6c819878ac85 analysis/analysis.css --- a/analysis/analysis.css Tue Mar 29 14:37:07 2016 +0100 +++ b/analysis/analysis.css Thu Mar 31 13:31:42 2016 +0100 @@ -7,4 +7,10 @@ padding-left: 15px; background-color: rgb(200,200,200); border: 2px dashed black; +} +table td tr{ + padding: 5px; +} +div.filter-entry{ + padding: 5px; } \ No newline at end of file diff -r b24d861c96b3 -r 6c819878ac85 analysis/analysis.js --- a/analysis/analysis.js Tue Mar 29 14:37:07 2016 +0100 +++ b/analysis/analysis.js Thu Mar 31 13:31:42 2016 +0100 @@ -2,11 +2,119 @@ * Analysis script for WAET */ -var chartContext; +// 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) +{ + name = String(name); + var selected = this.documentElement.getAllElementsByName(name); + return selected; +} + +Element.prototype.getAllElementsByName = function(name) +{ + name = String(name); + var selected = []; + var node = this.firstElementChild; + while(node != null) + { + if (node.getAttribute('name') == name) + { + selected.push(node); + } + if (node.childElementCount > 0) + { + selected = selected.concat(node.getAllElementsByName(name)); + } + node = node.nextElementSibling; + } + return selected; +} + +XMLDocument.prototype.getAllElementsByTagName = function(name) +{ + name = String(name); + var selected = this.documentElement.getAllElementsByTagName(name); + return selected; +} + +Element.prototype.getAllElementsByTagName = function(name) +{ + name = String(name); + var selected = []; + var node = this.firstElementChild; + while(node != null) + { + if (node.nodeName == name) + { + selected.push(node); + } + if (node.childElementCount > 0) + { + selected = selected.concat(node.getAllElementsByTagName(name)); + } + node = node.nextElementSibling; + } + return selected; +} + +// Firefox does not have an XMLDocument.prototype.getElementsByName +if (typeof XMLDocument.prototype.getElementsByName != "function") { + XMLDocument.prototype.getElementsByName = function(name) + { + name = String(name); + var node = this.documentElement.firstElementChild; + var selected = []; + while(node != null) + { + if (node.getAttribute('name') == name) + { + selected.push(node); + } + node = node.nextElementSibling; + } + return selected; + } +} + +var chartContext, testData; 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)); + } + }; + + // Handle network errors + req.onerror = function() { + reject(Error("Network Error")); + }; + + // Make the request + req.send(); + }); } function arrayMean(values) { @@ -115,30 +223,9 @@ } function Chart() { - this.valueData = null; - this.commentData = null; - this.loadStatus = 0; + this.valueData; this.charts = []; - var XMLHttp = new XMLHttpRequest(); - XMLHttp.parent = this; - XMLHttp.open("GET","../scripts/score_parser.php?format=JSON",true); - XMLHttp.onload = function() { - // Now we have the JSON data, extract - this.parent.valueData = JSON.parse(this.responseText); - this.parent.loadStatus++; - } - XMLHttp.send(); - var XMLHttp2 = new XMLHttpRequest(); - XMLHttp2.parent = this; - XMLHttp2.open("GET","../scripts/comment_parser.php?format=JSON",true); - XMLHttp2.onload = function() { - // Now we have the JSON data, extract - this.parent.commentData = JSON.parse(this.responseText); - this.parent.loadStatus++; - } - XMLHttp2.send(); - this.chartObject = function(name) { // Create the charting object this.name = name; @@ -491,4 +578,226 @@ } } } +} + +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("../test-schema.xsd").then(function(response){ + var parse = new DOMParser(); + self.specification.schema = parse.parseFromString(response,'text/xml'); + },function(error){ + console.log("ERROR: Could not get Test Schema"); + }); + this.update = function(url) { + var self = this; + get(url).then(function(response){ + var parse = new DOMParser(); + self.specification.decode(parse.parseFromString(response,'text/xml')); + interfaceContext.generateFilters(self.specification); + return true; + },function(error){ + console.log("ERROR: Could not get"+url); + return false; + }); + } + var get_test = new XMLHttpRequest(); + get_test.parent = this; + get_test.open("GET","../scripts/get_tests.php?format=JSON",true); + get_test.onload = function() { + this.parent.testSavedDiv.innerHTML = null; + var table = document.createElement("table"); + table.innerHTML = "Test FilenameCountInclude"; + this.parent.testSaves = JSON.parse(this.responseText); + for (var test of this.parent.testSaves.tests) { + var tableRow = document.createElement("tr"); + var tableRowFilename = document.createElement("td"); + tableRowFilename.textContent = test.testName; + var tableRowCount = document.createElement("td"); + tableRowCount.textContent = test.files.length; + tableRow.appendChild(tableRowFilename); + tableRow.appendChild(tableRowCount); + var tableRowInclude = document.createElement("td"); + var tableRowIncludeInput = document.createElement("input"); + tableRowIncludeInput.type = "radio"; + tableRowIncludeInput.name = "test-include"; + tableRowIncludeInput.setAttribute("source",test.testName); + tableRowIncludeInput.addEventListener("change",this.parent); + tableRowInclude.appendChild(tableRowIncludeInput); + tableRow.appendChild(tableRowInclude); + table.appendChild(tableRow); + } + this.parent.testSavedDiv.appendChild(table); + } + get_test.send(); + this.handleEvent = function(event) { + if (event.currentTarget.nodeName == "INPUT" && event.currentTarget.name == "test-include") { + // Changed the test specification + this.selectURL = event.currentTarget.getAttribute("source"); + this.update(this.selectURL); + } + } +} + +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.filterDOM = document.createElement("div"); + this.filterDOM.innerHTML = "

PreTest Filters

"; + this.filterObjects = []; + this.generateFilters = function(specification) { + // Filters are based on the pre and post global surverys + var FilterObject = function(parent,specification) { + this.parent = parent; + this.specification = specification; + this.rootDOM = document.createElement("div"); + this.rootDOM.innerHTML = "ID: "+specification.id+", Type: "+specification.type+""; + this.rootDOM.className = "filter-entry"; + this.handleEvent = function(event) { + switch(this.specification.type) { + case "number": + var name = event.currentTarget.name; + eval("this."+name+" = event.currentTarget.value"); + break; + case "checkbox": + break; + case "radio": + break; + } + this.parent.getFileCount(); + } + this.getFilterPairs = function() { + var pairs = []; + switch(this.specification.type) { + case "number": + if (this.min != "") { + pairs.push([specification.id+"-min",this.min]); + } + if (this.max != "") { + pairs.push([specification.id+"-max",this.max]); + } + break; + case "radio": + case "checkbox": + for (var i=0; i +

Web Audio Evaluation Toolbox: Analysis

+

Charts per test

diff -r b24d861c96b3 -r 6c819878ac85 core.js --- a/core.js Tue Mar 29 14:37:07 2016 +0100 +++ b/core.js Thu Mar 31 13:31:42 2016 +0100 @@ -28,6 +28,16 @@ // Add a prototype to the bufferNode to hold the computed LUFS loudness AudioBuffer.prototype.lufs = undefined; +// Convert relative URLs into absolutes +function escapeHTML(s) { + return s.split('&').join('&').split('<').join('<').split('"').join('"'); +} +function qualifyURL(url) { + var el= document.createElement('div'); + el.innerHTML= 'x'; + return el.firstChild.href; +} + // 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 @@ -1781,644 +1791,6 @@ console.log(outputSequence.toString()); // print randomised array to console return holdArr; } - -function Specification() { - // Handles the decoding of the project specification XML into a simple JavaScript Object. - - this.interface = null; - this.projectReturn = "null"; - this.randomiseOrder = null; - this.testPages = null; - this.pages = []; - this.metrics = null; - this.interfaces = null; - this.loudness = 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 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 {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 in attributes) - { - if (isNaN(Number(i)) == true){break;} - 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 in survey) { - if (isNaN(Number(i)) == true){break;} - 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 this.surveyNode(); - this.preTest.decode(this,survey[i]); - } - } 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 this.surveyNode(); - this.postTest.decode(this,survey[i]); - } - } - } - - var interfaceNode = setupNode.getElementsByTagName('interface'); - if (interfaceNode.length > 1) - { - this.errors.push("Only one node in the node allowed! Others except first ingnored!"); - } - this.interfaces = new this.interfaceNode(); - 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 - var commentboxprefix = root.createElement("commentboxprefix"); - commentboxprefix.textContent = this.commentBoxPrefix; - AHNode.appendChild(commentboxprefix); - - for (var i=0; i - for (var i=0; i - - - - - + + + + + + - + +