Mercurial > hg > webaudioevaluationtool
view js/specification.js @ 2562:9c167c0d6c26
Added video and youtube creation to test_create #134
author | Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk> |
---|---|
date | Fri, 02 Sep 2016 11:38:09 +0100 |
parents | 1647bb807186 |
children | 172c76d9414b |
line wrap: on
line source
function Specification() { // Handles the decoding of the project specification XML into a simple JavaScript Object. // <setup> attributes this.interface = null; this.projectReturn = null; this.returnURL = null; this.randomiseOrder = null; this.poolSize = null; this.loudness = null; this.sampleRate = null; this.calibration = null; this.crossFade = null; 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.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 { var rest = schema.getAllElementsByTagName("xs:restriction").concat(schema.getAllElementsByTagName("xs:enumeration")); if (rest.length > 0) { dataType = rest[0].getAttribute("base"); if (typeof dataType == "string") { dataType = dataType.substr(3); } else { dataType = "string"; } } 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=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) { case 'pre': case 'before': 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]); 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 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++) { 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+")"); } } root.appendChild(setup); // Survey node if (this.exitText != null) { var exitTextNode = RootDocument.createElement('exitText'); exitTextNode.textContent = this.exitText; setup.appendChild(exitTextNode); } setup.appendChild(this.preTest.encode(RootDocument)); setup.appendChild(this.postTest.encode(RootDocument)); setup.appendChild(this.metrics.encode(RootDocument)); setup.appendChild(this.interfaces.encode(RootDocument)); for (var page of this.pages) { root.appendChild(page.encode(RootDocument)); } return RootDocument; }; this.surveyNode = function(specification) { this.location = null; this.options = []; this.parent = null; 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.name = 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 }); } } } var conditionElements = child.getElementsByTagName("conditional"); for (var i=0; i<conditionElements.length; i++) { var condition = conditionElements[i]; var obj = { check: condition.getAttribute("check"), value: condition.getAttribute("value"), jumpToOnPass: condition.getAttribute("jumpToOnPass"), jumpToOnFail: condition.getAttribute("jumpToOnFail") } 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); node.id = this.id; 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) { case "checkbox": case "radio": 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.textContent = option.text; node.appendChild(optionNode); } break; case "number": if (this.min != undefined) {node.setAttribute("min", this.min);} if (this.max != undefined) {node.setAttribute("max", this.max);} break; case "question": if (this.boxsize != undefined) {node.setAttribute("boxsize",this.boxsize);} if (this.mandatory != undefined) {node.setAttribute("mandatory",this.mandatory);} break; case "video": if (this.mandatory != undefined) {node.setAttribute("mandatory",this.mandatory);} case "youtube": if (this.url != undefined) {node.setAttribute("url",this.url);} break; 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); node.appendChild(conditionDOM); } 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';} 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); } 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) { 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]; 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"); if (typeof name == "string") 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) { var child = doc.createElement("interfaceoption"); 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) { var child = doc.createElement("scalelabel"); child.setAttribute("position",scale.position); child.textContent = scale.text; scales.appendChild(child); } node.appendChild(scales); } return node; }; }; this.metricNode = function() { this.enabled = []; this.decode = function(parent, xml) { var children = xml.getElementsByTagName('metricenable'); for (var i in children) { if (isNaN(Number(i)) == true){break;} this.enabled.push(children[i].textContent); } } this.encode = function(doc) { var node = doc.createElement('metric'); 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); } return node; } } 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.label = null; 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.specification = specification; 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.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) { this.title = title[0].textContent; } // Get the Comment Box Prefix var CBP = xml.getElementsByTagName('commentboxprefix'); if (CBP.length != 0) { 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++) { 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(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)); AHNode.appendChild(this.postTest.encode(root)); 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.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"); node.id = this.id; 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) { var child = root.createElement("option"); 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.name = null; 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++) { 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+")"); } } return AENode; }; }; }; }