nicholas@2224: function Specification() { nicholas@2573: // Handles the decoding of the project specification XML into a simple JavaScript Object. nicholas@2573: nicholas@2378: // attributes nicholas@2573: this.interface = null; nicholas@2573: this.projectReturn = null; nicholas@2303: this.returnURL = null; nicholas@2573: this.randomiseOrder = null; nicholas@2573: this.poolSize = null; nicholas@2378: this.loudness = null; nicholas@2378: this.sampleRate = null; nicholas@2378: this.calibration = null; nicholas@2378: this.crossFade = null; nicholas@2378: this.preSilence = null; nicholas@2378: this.postSilence = null; n@2426: this.playOne = null; nicholas@2573: nicholas@2378: // nodes nicholas@2378: this.metrics = null; nicholas@2378: this.preTest = undefined; nicholas@2378: this.postTest = undefined; nicholas@2573: this.pages = []; nicholas@2573: this.interfaces = null; nicholas@2573: this.errors = []; nicholas@2573: this.schema = null; nicholas@2224: this.exitText = "Thank you."; nicholas@2573: nicholas@2573: this.processAttribute = function (attribute, schema, schemaRoot) { nicholas@2573: // attribute is the string returned from getAttribute on the XML nicholas@2573: // schema is the node nicholas@2573: if (schema.getAttribute('name') == undefined && schema.getAttribute('ref') != undefined) { nicholas@2573: schema = schemaRoot.getAllElementsByName(schema.getAttribute('ref'))[0]; nicholas@2573: } nicholas@2573: var defaultOpt = schema.getAttribute('default'); nicholas@2573: if (attribute == null) { nicholas@2573: attribute = defaultOpt; nicholas@2573: } nicholas@2573: var dataType = schema.getAttribute('type'); nicholas@2573: if (typeof dataType == "string") { nicholas@2573: dataType = dataType.substr(3); nicholas@2573: } else { nicholas@2224: var rest = schema.getAllElementsByTagName("xs:restriction").concat(schema.getAllElementsByTagName("xs:enumeration")); nicholas@2224: if (rest.length > 0) { nicholas@2224: dataType = rest[0].getAttribute("base"); nicholas@2224: if (typeof dataType == "string") { nicholas@2224: dataType = dataType.substr(3); nicholas@2224: } else { nicholas@2224: dataType = "string"; nicholas@2224: } nicholas@2224: } else { nicholas@2224: dataType = "string"; nicholas@2224: } nicholas@2224: } nicholas@2573: if (attribute == null) { nicholas@2573: return attribute; nicholas@2573: } nicholas@2573: switch (dataType) { nicholas@2573: case "boolean": nicholas@2573: if (attribute == 'true') { nicholas@2573: attribute = true; nicholas@2573: } else { nicholas@2573: attribute = false; nicholas@2573: } nicholas@2573: break; nicholas@2573: case "negativeInteger": nicholas@2573: case "positiveInteger": nicholas@2573: case "nonNegativeInteger": nicholas@2573: case "nonPositiveInteger": nicholas@2573: case "integer": nicholas@2573: case "decimal": nicholas@2573: case "short": nicholas@2573: attribute = Number(attribute); nicholas@2573: break; nicholas@2573: case "string": nicholas@2573: default: nicholas@2573: attribute = String(attribute); nicholas@2573: break; nicholas@2573: } nicholas@2573: return attribute; nicholas@2573: }; nicholas@2573: nicholas@2573: this.decode = function (projectXML) { nicholas@2573: this.errors = []; nicholas@2573: // projectXML - DOM Parsed document nicholas@2573: this.projectXML = projectXML.childNodes[0]; nicholas@2573: var setupNode = projectXML.getElementsByTagName('setup')[0]; nicholas@2573: var schemaSetup = this.schema.getAllElementsByName('setup')[0]; nicholas@2573: // First decode the attributes nicholas@2573: var attributes = schemaSetup.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < attributes.length; i++) { nicholas@2573: var attributeName = attributes[i].getAttribute('name') || attributes[i].getAttribute('ref'); nicholas@2573: var projectAttr = setupNode.getAttribute(attributeName); nicholas@2573: projectAttr = this.processAttribute(projectAttr, attributes[i], this.schema); nicholas@2573: switch (typeof projectAttr) { nicholas@2573: case "number": nicholas@2573: case "boolean": nicholas@2573: eval('this.' + attributeName + ' = ' + projectAttr); nicholas@2573: break; nicholas@2573: case "string": nicholas@2573: eval('this.' + attributeName + ' = "' + projectAttr + '"'); nicholas@2573: break; nicholas@2573: } nicholas@2573: nicholas@2573: } nicholas@2573: nicholas@2224: var exitTextNode = setupNode.getElementsByTagName('exitText'); nicholas@2224: if (exitTextNode.length == 1) { nicholas@2224: this.exitText = exitTextNode[0].textContent; nicholas@2224: } nicholas@2573: nicholas@2573: this.metrics = new this.metricNode(); nicholas@2573: nicholas@2573: this.metrics.decode(this, setupNode.getElementsByTagName('metric')[0]); nicholas@2573: nicholas@2573: // Now process the survey node options nicholas@2573: var survey = setupNode.getElementsByTagName('survey'); nicholas@2573: for (var i = 0; i < survey.length; i++) { nicholas@2573: var location = survey[i].getAttribute('location'); nicholas@2573: switch (location) { nicholas@2257: case 'pre': nicholas@2257: case 'before': nicholas@2573: this.preTest = new this.surveyNode(this); nicholas@2573: this.preTest.decode(this, survey[i]); nicholas@2257: break; nicholas@2257: case 'post': nicholas@2257: case 'after': b@2437: this.postTest = new this.surveyNode(this); nicholas@2573: this.postTest.decode(this, survey[i]); nicholas@2257: break; nicholas@2257: } nicholas@2573: } nicholas@2573: nicholas@2573: var interfaceNode = setupNode.getElementsByTagName('interface'); nicholas@2573: if (interfaceNode.length > 1) { nicholas@2573: this.errors.push("Only one node in the node allowed! Others except first ingnored!"); nicholas@2573: } nicholas@2573: this.interfaces = new this.interfaceNode(this); nicholas@2573: if (interfaceNode.length != 0) { nicholas@2573: interfaceNode = interfaceNode[0]; nicholas@2573: this.interfaces.decode(this, interfaceNode, this.schema.getAllElementsByName('interface')[1]); nicholas@2573: } nicholas@2573: nicholas@2573: // Page tags nicholas@2573: var pageTags = projectXML.getElementsByTagName('page'); nicholas@2573: var pageSchema = this.schema.getAllElementsByName('page')[0]; nicholas@2573: for (var i = 0; i < pageTags.length; i++) { nicholas@2573: var node = new this.page(this); nicholas@2573: node.decode(this, pageTags[i], pageSchema); nicholas@2573: this.pages.push(node); nicholas@2573: } nicholas@2573: }; nicholas@2573: nicholas@2573: this.encode = function () { nicholas@2573: var RootDocument = document.implementation.createDocument(null, "waet"); nicholas@2573: var root = RootDocument.firstChild; nicholas@2573: root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); nicholas@2573: root.setAttribute("xsi:noNamespaceSchemaLocation", "test-schema.xsd"); nicholas@2573: // Build setup node nicholas@2224: var setup = RootDocument.createElement("setup"); nicholas@2224: var schemaSetup = this.schema.getAllElementsByName('setup')[0]; nicholas@2224: // First decode the attributes nicholas@2224: var attributes = schemaSetup.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < attributes.length; i++) { nicholas@2224: var name = attributes[i].getAttribute("name"); nicholas@2224: if (name == undefined) { nicholas@2224: name = attributes[i].getAttribute("ref"); nicholas@2224: } nicholas@2573: if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { nicholas@2573: eval("setup.setAttribute('" + name + "',this." + name + ")"); nicholas@2224: } nicholas@2224: } nicholas@2224: root.appendChild(setup); nicholas@2224: // Survey node nicholas@2224: if (this.exitText != null) { nicholas@2224: var exitTextNode = RootDocument.createElement('exitText'); nicholas@2224: exitTextNode.textContent = this.exitText; nicholas@2224: setup.appendChild(exitTextNode); nicholas@2224: } nicholas@2224: setup.appendChild(this.preTest.encode(RootDocument)); nicholas@2224: setup.appendChild(this.postTest.encode(RootDocument)); nicholas@2224: setup.appendChild(this.metrics.encode(RootDocument)); nicholas@2224: setup.appendChild(this.interfaces.encode(RootDocument)); nicholas@2573: for (var page of this.pages) { nicholas@2224: root.appendChild(page.encode(RootDocument)); nicholas@2224: } nicholas@2573: return RootDocument; nicholas@2573: }; nicholas@2573: nicholas@2573: this.surveyNode = function (specification) { nicholas@2573: this.location = null; nicholas@2573: this.options = []; nicholas@2224: this.parent = null; nicholas@2573: this.schema = specification.schema.getAllElementsByName('survey')[0]; nicholas@2224: this.specification = specification; nicholas@2573: nicholas@2573: this.OptionNode = function (specification) { nicholas@2573: this.type = undefined; nicholas@2573: this.schema = specification.schema.getAllElementsByName('surveyentry')[0]; nicholas@2573: this.id = undefined; nicholas@2224: this.name = undefined; nicholas@2573: this.mandatory = undefined; nicholas@2573: this.statement = undefined; nicholas@2573: this.boxsize = undefined; nicholas@2573: this.options = []; nicholas@2573: this.min = undefined; nicholas@2573: this.max = undefined; nicholas@2573: this.step = undefined; nicholas@2464: this.conditions = []; nicholas@2573: nicholas@2573: this.decode = function (parent, child) { nicholas@2573: var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i in attributeMap) { nicholas@2573: if (isNaN(Number(i)) == true) { nicholas@2573: break; nicholas@2573: } nicholas@2573: var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); nicholas@2573: var projectAttr = child.getAttribute(attributeName); nicholas@2573: projectAttr = parent.processAttribute(projectAttr, attributeMap[i], parent.schema); nicholas@2573: switch (typeof projectAttr) { nicholas@2573: case "number": nicholas@2573: case "boolean": nicholas@2573: eval('this.' + attributeName + ' = ' + projectAttr); nicholas@2573: break; nicholas@2573: case "string": nicholas@2573: eval('this.' + attributeName + ' = "' + projectAttr + '"'); nicholas@2573: break; nicholas@2573: } nicholas@2573: } nicholas@2573: this.statement = child.getElementsByTagName('statement')[0].textContent; nicholas@2573: if (this.type == "checkbox" || this.type == "radio") { nicholas@2573: var children = child.getElementsByTagName('option'); nicholas@2573: if (children.length == null) { nicholas@2573: console.log('Malformed' + child.nodeName + 'entry'); nicholas@2573: this.statement = 'Malformed' + child.nodeName + 'entry'; nicholas@2573: this.type = 'statement'; nicholas@2573: } else { nicholas@2573: this.options = []; nicholas@2573: for (var i = 0; i < children.length; i++) { nicholas@2573: this.options.push({ nicholas@2573: name: children[i].getAttribute('name'), nicholas@2573: text: children[i].textContent nicholas@2573: }); nicholas@2573: } nicholas@2573: } nicholas@2573: } nicholas@2464: var conditionElements = child.getElementsByTagName("conditional"); nicholas@2573: for (var i = 0; i < conditionElements.length; i++) { nicholas@2464: var condition = conditionElements[i]; nicholas@2464: var obj = { nicholas@2464: check: condition.getAttribute("check"), nicholas@2464: value: condition.getAttribute("value"), nicholas@2464: jumpToOnPass: condition.getAttribute("jumpToOnPass"), nicholas@2464: jumpToOnFail: condition.getAttribute("jumpToOnFail") nicholas@2464: } nicholas@2464: this.conditions.push(obj); nicholas@2464: } nicholas@2573: }; nicholas@2573: nicholas@2573: this.exportXML = function (doc) { nicholas@2573: var node = doc.createElement('surveyentry'); nicholas@2573: node.setAttribute('type', this.type); nicholas@2573: var statement = doc.createElement('statement'); nicholas@2573: statement.textContent = this.statement; nicholas@2573: node.appendChild(statement); nicholas@2224: node.id = this.id; nicholas@2573: if (this.name != undefined) { nicholas@2573: node.setAttribute("name", this.name); nicholas@2573: } nicholas@2573: if (this.mandatory != undefined) { nicholas@2573: node.setAttribute("mandatory", this.mandatory); nicholas@2573: } nicholas@2224: node.id = this.id; nicholas@2573: if (this.name != undefined) { nicholas@2573: node.setAttribute("name", this.name); nicholas@2573: } nicholas@2573: switch (this.type) { nicholas@2224: case "checkbox": nicholas@2566: if (this.min != undefined) { nicholas@2566: node.setAttribute("min", this.min); nicholas@2566: } else { nicholas@2566: node.setAttribute("min", "0"); nicholas@2566: } nicholas@2566: if (this.max != undefined) { nicholas@2566: node.setAttribute("max", this.max); nicholas@2566: } else { nicholas@2573: node.setAttribute("max", "undefined"); nicholas@2566: } nicholas@2224: case "radio": nicholas@2573: for (var i = 0; i < this.options.length; i++) { nicholas@2224: var option = this.options[i]; nicholas@2224: var optionNode = doc.createElement("option"); nicholas@2573: optionNode.setAttribute("name", option.name); nicholas@2224: optionNode.textContent = option.text; nicholas@2224: node.appendChild(optionNode); nicholas@2224: } nicholas@2562: break; nicholas@2224: case "number": nicholas@2573: if (this.min != undefined) { nicholas@2573: node.setAttribute("min", this.min); nicholas@2573: } nicholas@2573: if (this.max != undefined) { nicholas@2573: node.setAttribute("max", this.max); nicholas@2573: } nicholas@2562: break; nicholas@2224: case "question": nicholas@2573: if (this.boxsize != undefined) { nicholas@2573: node.setAttribute("boxsize", this.boxsize); nicholas@2573: } nicholas@2573: if (this.mandatory != undefined) { nicholas@2573: node.setAttribute("mandatory", this.mandatory); nicholas@2573: } nicholas@2562: break; nicholas@2562: case "video": nicholas@2573: if (this.mandatory != undefined) { nicholas@2573: node.setAttribute("mandatory", this.mandatory); nicholas@2573: } nicholas@2562: case "youtube": nicholas@2573: if (this.url != undefined) { nicholas@2573: node.setAttribute("url", this.url); nicholas@2573: } nicholas@2562: break; nicholas@2224: default: nicholas@2224: break; nicholas@2224: } nicholas@2465: for (var condition of this.conditions) { nicholas@2465: var conditionDOM = doc.createElement("conditional"); nicholas@2573: conditionDOM.setAttribute("check", condition.check); nicholas@2573: conditionDOM.setAttribute("value", condition.value); nicholas@2573: conditionDOM.setAttribute("jumpToOnPass", condition.jumpToOnPass); nicholas@2573: conditionDOM.setAttribute("jumpToOnFail", condition.jumpToOnFail); nicholas@2465: node.appendChild(conditionDOM); nicholas@2465: } nicholas@2573: return node; nicholas@2573: }; nicholas@2573: }; nicholas@2573: this.decode = function (parent, xml) { nicholas@2224: this.parent = parent; nicholas@2573: this.location = xml.getAttribute('location'); nicholas@2573: if (this.location == 'before') { nicholas@2573: this.location = 'pre'; nicholas@2573: } else if (this.location == 'after') { nicholas@2573: this.location = 'post'; nicholas@2573: } nicholas@2260: var children = xml.getAllElementsByTagName('surveyentry'); nicholas@2573: for (var i = 0; i < children.length; i++) { nicholas@2573: var node = new this.OptionNode(this.specification); nicholas@2573: node.decode(parent, children[i]); nicholas@2573: this.options.push(node); nicholas@2573: } nicholas@2257: if (this.options.length == 0) { nicholas@2257: console.log("Empty survey node"); nicholas@2257: console.log(this); nicholas@2257: } nicholas@2573: }; nicholas@2573: this.encode = function (doc) { nicholas@2573: var node = doc.createElement('survey'); nicholas@2573: node.setAttribute('location', this.location); nicholas@2573: for (var i = 0; i < this.options.length; i++) { nicholas@2573: node.appendChild(this.options[i].exportXML(doc)); nicholas@2573: } nicholas@2573: return node; nicholas@2573: }; nicholas@2573: }; nicholas@2573: nicholas@2573: this.interfaceNode = function (specification) { nicholas@2573: this.title = null; nicholas@2573: this.name = null; nicholas@2573: this.options = []; nicholas@2573: this.scales = []; nicholas@2573: this.schema = specification.schema.getAllElementsByName('interface')[1]; nicholas@2573: nicholas@2573: this.decode = function (parent, xml) { nicholas@2573: this.name = xml.getAttribute('name'); nicholas@2573: var titleNode = xml.getElementsByTagName('title'); nicholas@2573: if (titleNode.length == 1) { nicholas@2573: this.title = titleNode[0].textContent; nicholas@2573: } nicholas@2573: var interfaceOptionNodes = xml.getElementsByTagName('interfaceoption'); nicholas@2573: // Extract interfaceoption node schema nicholas@2573: var interfaceOptionNodeSchema = this.schema.getAllElementsByName('interfaceoption')[0]; nicholas@2573: var attributeMap = interfaceOptionNodeSchema.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < interfaceOptionNodes.length; i++) { nicholas@2573: var ioNode = interfaceOptionNodes[i]; nicholas@2573: var option = {}; nicholas@2573: for (var j = 0; j < attributeMap.length; j++) { nicholas@2573: var attributeName = attributeMap[j].getAttribute('name') || attributeMap[j].getAttribute('ref'); nicholas@2573: var projectAttr = ioNode.getAttribute(attributeName); nicholas@2573: if (parent.processAttribute) { nicholas@2224: parent.processAttribute(projectAttr, attributeMap[j], parent.schema) nicholas@2224: } else { nicholas@2224: parent.parent.processAttribute(projectAttr, attributeMap[j], parent.parent.schema) nicholas@2224: } nicholas@2573: switch (typeof projectAttr) { nicholas@2573: case "number": nicholas@2573: case "boolean": nicholas@2573: eval('option.' + attributeName + ' = ' + projectAttr); nicholas@2573: break; nicholas@2573: case "string": nicholas@2573: eval('option.' + attributeName + ' = "' + projectAttr + '"'); nicholas@2573: break; nicholas@2573: } nicholas@2573: } nicholas@2573: this.options.push(option); nicholas@2573: } nicholas@2573: nicholas@2573: // Now the scales nodes nicholas@2573: var scaleParent = xml.getElementsByTagName('scales'); nicholas@2573: if (scaleParent.length == 1) { nicholas@2573: scaleParent = scaleParent[0]; nicholas@2252: var scalelabels = scaleParent.getAllElementsByTagName('scalelabel'); nicholas@2573: for (var i = 0; i < scalelabels.length; i++) { nicholas@2573: this.scales.push({ nicholas@2573: text: scalelabels[i].textContent, nicholas@2573: position: Number(scalelabels[i].getAttribute('position')) nicholas@2573: }); nicholas@2573: } nicholas@2573: } nicholas@2573: }; nicholas@2573: nicholas@2573: this.encode = function (doc) { nicholas@2573: var node = doc.createElement("interface"); nicholas@2224: if (typeof name == "string") nicholas@2573: node.setAttribute("name", this.name); nicholas@2243: if (typeof this.title == "string") { nicholas@2243: var titleNode = doc.createElement("title"); nicholas@2243: titleNode.textContent = this.title; nicholas@2243: node.appendChild(titleNode); nicholas@2243: } nicholas@2573: for (var option of this.options) { nicholas@2224: var child = doc.createElement("interfaceoption"); nicholas@2573: child.setAttribute("type", option.type); nicholas@2573: child.setAttribute("name", option.name); nicholas@2224: node.appendChild(child); nicholas@2224: } nicholas@2224: if (this.scales.length != 0) { nicholas@2224: var scales = doc.createElement("scales"); nicholas@2573: for (var scale of this.scales) { nicholas@2224: var child = doc.createElement("scalelabel"); nicholas@2573: child.setAttribute("position", scale.position); nicholas@2224: child.textContent = scale.text; nicholas@2224: scales.appendChild(child); nicholas@2224: } nicholas@2224: node.appendChild(scales); nicholas@2224: } nicholas@2224: return node; nicholas@2573: }; nicholas@2573: }; nicholas@2573: nicholas@2573: this.metricNode = function () { nicholas@2224: this.enabled = []; nicholas@2573: this.decode = function (parent, xml) { nicholas@2224: var children = xml.getElementsByTagName('metricenable'); nicholas@2573: for (var i in children) { nicholas@2573: if (isNaN(Number(i)) == true) { nicholas@2573: break; nicholas@2573: } nicholas@2224: this.enabled.push(children[i].textContent); nicholas@2224: } nicholas@2224: } nicholas@2573: this.encode = function (doc) { nicholas@2224: var node = doc.createElement('metric'); nicholas@2573: for (var i in this.enabled) { nicholas@2573: if (isNaN(Number(i)) == true) { nicholas@2573: break; nicholas@2573: } nicholas@2224: var child = doc.createElement('metricenable'); nicholas@2224: child.textContent = this.enabled[i]; nicholas@2224: node.appendChild(child); nicholas@2224: } nicholas@2224: return node; nicholas@2224: } nicholas@2224: } nicholas@2573: nicholas@2573: this.page = function (specification) { nicholas@2573: this.presentedId = undefined; nicholas@2573: this.id = undefined; nicholas@2470: this.title = undefined; nicholas@2573: this.hostURL = undefined; nicholas@2573: this.randomiseOrder = undefined; nicholas@2573: this.loop = undefined; nicholas@2573: this.outsideReference = null; nicholas@2573: this.loudness = null; nicholas@2224: this.label = null; nicholas@2573: this.labelStart = ""; nicholas@2573: this.preTest = null; nicholas@2573: this.postTest = null; nicholas@2573: this.interfaces = []; n@2426: this.playOne = null; nicholas@2573: this.commentBoxPrefix = "Comment on track"; nicholas@2573: this.audioElements = []; nicholas@2573: this.commentQuestions = []; nicholas@2573: this.schema = specification.schema.getAllElementsByName("page")[0]; nicholas@2224: this.specification = specification; nicholas@2224: this.parent = null; nicholas@2573: nicholas@2573: this.decode = function (parent, xml) { nicholas@2224: this.parent = parent; n@2579: var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); n@2579: for (var i = 0; i < attributeMap.length; i++) { n@2579: var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); n@2579: var projectAttr = xml.getAttribute(attributeName); n@2579: projectAttr = parent.processAttribute(projectAttr, attributeMap[i], parent.schema); n@2579: switch (typeof projectAttr) { n@2579: case "number": n@2579: case "boolean": n@2579: eval('this.' + attributeName + ' = ' + projectAttr); n@2579: break; n@2579: case "string": n@2579: eval('this.' + attributeName + ' = "' + projectAttr + '"'); n@2579: break; n@2579: } n@2579: } n@2579: nicholas@2470: // Get the title nicholas@2470: var title = xml.getElementsByTagName('title'); nicholas@2501: if (title.length != 0 && title[0].parentElement == xml) { nicholas@2470: this.title = title[0].textContent; nicholas@2470: } n@2579: n@2579: // Get the Comment Box Prefix n@2579: var CBP = xml.getElementsByTagName('commentboxprefix'); n@2579: if (CBP.length != 0 && CBP[0].parentElement == xml) { n@2579: this.commentBoxPrefix = CBP[0].textContent; n@2579: } n@2579: n@2579: // Now decode the interfaces n@2579: var interfaceNode = xml.getElementsByTagName('interface'); n@2579: for (var i = 0; i < interfaceNode.length; i++) { n@2579: var node = new parent.interfaceNode(this.specification); n@2579: node.decode(this, interfaceNode[i], parent.schema.getAllElementsByName('interface')[1]); n@2579: this.interfaces.push(node); n@2579: } n@2579: n@2579: // Now process the survey node options n@2579: var survey = xml.getElementsByTagName('survey'); n@2579: var surveySchema = parent.schema.getAllElementsByName('survey')[0]; n@2579: for (var i = 0; i < survey.length; i++) { n@2579: var location = survey[i].getAttribute('location'); n@2579: if (location == 'pre' || location == 'before') { n@2579: if (this.preTest != null) { n@2579: this.errors.push("Already a pre/before test survey defined! Ignoring second!!"); n@2579: } else { n@2579: this.preTest = new parent.surveyNode(this.specification); n@2579: this.preTest.decode(parent, survey[i], surveySchema); n@2579: } n@2579: } else if (location == 'post' || location == 'after') { n@2579: if (this.postTest != null) { n@2579: this.errors.push("Already a post/after test survey defined! Ignoring second!!"); n@2579: } else { n@2579: this.postTest = new parent.surveyNode(this.specification); n@2579: this.postTest.decode(parent, survey[i], surveySchema); n@2579: } n@2579: } n@2579: } n@2579: n@2579: // Now process the audioelement tags n@2579: var audioElements = xml.getElementsByTagName('audioelement'); n@2579: for (var i = 0; i < audioElements.length; i++) { n@2579: var node = new this.audioElementNode(this.specification); n@2579: node.decode(this, audioElements[i]); n@2579: this.audioElements.push(node); n@2579: } n@2579: n@2579: // Now decode the commentquestions n@2579: var cqNode = xml.getElementsByTagName('commentquestions'); n@2579: if (cqNode.length != 0) { n@2579: cqNode = cqNode[0]; n@2579: var commentQuestions = cqNode.children; n@2579: for (var i = 0; i < commentQuestions.length; i++) { n@2579: var node = new this.commentQuestionNode(this.specification); n@2579: node.decode(parent, commentQuestions[i]); n@2579: this.commentQuestions.push(node); n@2579: } n@2579: } n@2579: }; n@2579: n@2579: this.encode = function (root) { n@2579: var AHNode = root.createElement("page"); nicholas@2224: // First decode the attributes nicholas@2224: var attributes = this.schema.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < attributes.length; i++) { nicholas@2224: var name = attributes[i].getAttribute("name"); nicholas@2224: if (name == undefined) { nicholas@2224: name = attributes[i].getAttribute("ref"); nicholas@2224: } nicholas@2573: if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { nicholas@2573: eval("AHNode.setAttribute('" + name + "',this." + name + ")"); nicholas@2224: } nicholas@2224: } nicholas@2573: if (this.loudness != null) { nicholas@2573: AHNode.setAttribute("loudness", this.loudness); nicholas@2573: } nicholas@2224: // nicholas@2224: var commentboxprefix = root.createElement("commentboxprefix"); nicholas@2224: commentboxprefix.textContent = this.commentBoxPrefix; nicholas@2224: AHNode.appendChild(commentboxprefix); nicholas@2573: nicholas@2573: for (var i = 0; i < this.interfaces.length; i++) { nicholas@2573: AHNode.appendChild(this.interfaces[i].encode(root)); nicholas@2573: } nicholas@2573: nicholas@2573: for (var i = 0; i < this.audioElements.length; i++) { nicholas@2573: AHNode.appendChild(this.audioElements[i].encode(root)); nicholas@2573: } nicholas@2573: // Create nicholas@2573: for (var i = 0; i < this.commentQuestions.length; i++) { nicholas@2573: AHNode.appendChild(this.commentQuestions[i].encode(root)); nicholas@2573: } nicholas@2573: nicholas@2573: AHNode.appendChild(this.preTest.encode(root)); nicholas@2224: AHNode.appendChild(this.postTest.encode(root)); nicholas@2573: return AHNode; nicholas@2573: }; nicholas@2573: nicholas@2573: this.commentQuestionNode = function (specification) { nicholas@2573: this.id = null; nicholas@2224: this.name = undefined; nicholas@2573: this.type = undefined; nicholas@2573: this.statement = undefined; nicholas@2573: this.schema = specification.schema.getAllElementsByName('commentquestion')[0]; nicholas@2573: this.decode = function (parent, xml) { nicholas@2573: this.id = xml.id; nicholas@2224: this.name = xml.getAttribute('name'); n@2579: switch (xml.nodeName) { n@2579: case "commentradio": n@2579: this.type = "radio"; n@2579: this.options = []; n@2579: break; n@2579: case "commentcheckbox": n@2579: this.type = "checkbox"; n@2579: this.options = []; n@2579: break; n@2579: case "commentslider": n@2579: this.type = "slider"; n@2579: this.min = undefined; n@2579: this.max = undefined; n@2579: this.step = undefined; n@2579: break; n@2579: case "commentquestion": n@2579: default: n@2579: this.type = "question"; n@2579: break; n@2579: } nicholas@2573: this.statement = xml.getElementsByTagName('statement')[0].textContent; n@2579: if (this.type == "radio" || this.type == "checkbox") { n@2579: var optNodes = xml.getElementsByTagName('option'); n@2579: for (var i = 0; i < optNodes.length; i++) { n@2579: var optNode = optNodes[i]; n@2579: this.options.push({ n@2579: name: optNode.getAttribute('name'), n@2579: text: optNode.textContent n@2579: }); n@2579: } n@2579: } n@2579: if (this.type == "slider") { n@2579: this.min = Number(xml.getAttribute("min")); n@2579: this.max = Number(xml.getAttribute("max")); n@2579: this.step = Number(xml.getAttribute("step")); n@2579: if (this.step == undefined) { n@2579: this.step = 1; n@2579: } n@2579: this.value = Number(xml.getAttribute("value")); n@2579: if (this.value == undefined) { n@2579: this.value = min; n@2579: } nicholas@2573: } nicholas@2573: }; nicholas@2573: nicholas@2573: this.encode = function (root) { n@2579: var node; n@2579: switch (this.type) { n@2579: case "radio": n@2579: node = root.createElement("commentradio"); n@2579: break; n@2579: case "checkbox": n@2579: node = root.createElement("commentcheckbox"); n@2579: break; n@2579: case "slider": n@2579: node = root.createElement("commentslider"); n@2579: break; n@2579: case "question": n@2579: default: n@2579: node = root.createElement("commentquestion"); n@2579: break; n@2579: } nicholas@2224: node.id = this.id; nicholas@2573: node.setAttribute("type", this.type); nicholas@2573: if (this.name != undefined) { nicholas@2573: node.setAttribute("name", this.name); nicholas@2573: } nicholas@2224: var statement = root.createElement("statement"); nicholas@2224: statement.textContent = this.statement; nicholas@2224: node.appendChild(statement); n@2579: if (this.type == "radio" || this.type == "checkbox") { n@2579: for (var option of this.options) { n@2579: var child = root.createElement("option"); n@2579: child.setAttribute("name", option.name); n@2579: child.textContent = option.text; n@2579: node.appendChild(child); n@2579: } n@2579: } n@2579: if (this.type == "slider") { n@2579: node.setAttribute("min", this.min); n@2579: node.setAttribute("max", this.max); n@2579: if (this.step !== 1) { n@2579: node.setAttribute("step", this.step); n@2579: } n@2579: if (this.value !== this.min) { n@2579: node.setAttribute("value", this.value); n@2579: } nicholas@2224: } nicholas@2224: return node; nicholas@2573: }; nicholas@2573: }; nicholas@2573: nicholas@2573: this.audioElementNode = function (specification) { nicholas@2573: this.url = null; nicholas@2573: this.id = null; nicholas@2224: this.name = null; nicholas@2573: this.parent = null; nicholas@2573: this.type = null; nicholas@2573: this.marker = null; nicholas@2573: this.enforce = false; nicholas@2573: this.gain = 0.0; nicholas@2409: this.label = null; nicholas@2460: this.startTime = undefined; nicholas@2460: this.stopTime = undefined; nicholas@2573: this.schema = specification.schema.getAllElementsByName('audioelement')[0];; nicholas@2573: this.parent = null; nicholas@2573: this.decode = function (parent, xml) { nicholas@2573: this.parent = parent; nicholas@2573: var attributeMap = this.schema.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < attributeMap.length; i++) { nicholas@2573: var attributeName = attributeMap[i].getAttribute('name') || attributeMap[i].getAttribute('ref'); nicholas@2573: var projectAttr = xml.getAttribute(attributeName); nicholas@2573: projectAttr = parent.parent.processAttribute(projectAttr, attributeMap[i], parent.parent.schema); nicholas@2573: switch (typeof projectAttr) { nicholas@2573: case "number": nicholas@2573: case "boolean": nicholas@2573: eval('this.' + attributeName + ' = ' + projectAttr); nicholas@2573: break; nicholas@2573: case "string": nicholas@2573: eval('this.' + attributeName + ' = "' + projectAttr + '"'); nicholas@2573: break; nicholas@2573: } nicholas@2573: } nicholas@2573: nicholas@2573: }; nicholas@2573: this.encode = function (root) { nicholas@2573: var AENode = root.createElement("audioelement"); nicholas@2573: var attributes = this.schema.getAllElementsByTagName('xs:attribute'); nicholas@2573: for (var i = 0; i < attributes.length; i++) { nicholas@2224: var name = attributes[i].getAttribute("name"); nicholas@2224: if (name == undefined) { nicholas@2224: name = attributes[i].getAttribute("ref"); nicholas@2224: } nicholas@2573: if (eval("this." + name + " != undefined") || attributes[i].getAttribute("use") == "required") { nicholas@2573: eval("AENode.setAttribute('" + name + "',this." + name + ")"); nicholas@2224: } nicholas@2224: } nicholas@2573: return AENode; nicholas@2573: }; nicholas@2573: }; nicholas@2573: }; b@2437: }