changeset 2464:75bd7b5dc522

Implemented #5
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Thu, 23 Jun 2016 13:44:17 +0100
parents fda7ee7bb914
children af42b5492f46
files js/core.js js/specification.js tests/examples/project.xml xml/test-schema.xsd
diffstat 4 files changed, 152 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/js/core.js	Thu Jun 23 12:57:46 2016 +0100
+++ b/js/core.js	Thu Jun 23 13:44:17 2016 +0100
@@ -859,6 +859,39 @@
 				console.log("Question Response: "+ textArea.value);
 				node.response = textArea.value;
 			}
+            // Perform the conditional
+            for (var condition of node.specification.conditions) {
+                var pass = false;
+                switch(condition.check) {
+                    case "equals":
+                        if (textArea.value == condition.value) {
+                            pass = true;
+                        }
+                        break;
+                    case "greaterThan":
+                    case "lessThan":
+                        console.log("Survey Element of type 'question' cannot interpret greaterThan/lessThan conditions. IGNORING");
+                        break;
+                    case "contains":
+                        if (textArea.value.includes(condition.value)) {
+                            pass = true;
+                        }
+                        break;
+                }
+                var jumpID;
+                if (pass) {
+                    jumpID = condition.jumpToOnPass;
+                } else {
+                    jumpID = condition.jumpToOnFail;
+                }
+                if (jumpID != undefined) {
+                    var index = this.popupOptions.findIndex(function(item,index,element){
+                        if (item.specification.id == jumpID) {return true;} else {return false;}
+                    },this);
+                    this.currentIndex = index-1;
+                    break;
+                }
+            }
 		} else if (node.specification.type == 'checkbox') {
 			// Must extract checkbox data
 			console.log("Checkbox: "+ node.specification.statement);
@@ -872,6 +905,38 @@
 				});
 				console.log(node.specification.options[i].name+": "+ inputs[i].checked);
 			}
+            // Perform the conditional
+            for (var condition of node.specification.conditions) {
+                var pass = false;
+                switch(condition.check) {
+                    case "equals":
+                    case "greaterThan":
+                    case "lessThan":
+                        console.log("Survey Element of type 'checkbox' cannot interpret equals/greaterThan/lessThan conditions. IGNORING");
+                        break;
+                    case "contains":
+                        for (var response of node.response) {
+                            if (response.name == condition.value && response.checked) {
+                                pass = true;
+                                break;
+                            }
+                        }
+                        break;
+                }
+                var jumpID;
+                if (pass) {
+                    jumpID = condition.jumpToOnPass;
+                } else {
+                    jumpID = condition.jumpToOnFail;
+                }
+                if (jumpID != undefined) {
+                    var index = this.popupOptions.findIndex(function(item,index,element){
+                        if (item.specification.id == jumpID) {return true;} else {return false;}
+                    },this);
+                    this.currentIndex = index-1;
+                    break;
+                }
+            }
 		} else if (node.specification.type == "radio") {
 			var optHold = this.popupResponse;
 			console.log("Radio: "+ node.specification.statement);
@@ -894,6 +959,35 @@
 				}
 				i++;
 			}
+            // Perform the conditional
+            for (var condition of node.specification.conditions) {
+                var pass = false;
+                switch(condition.check) {
+                    case "contains":
+                    case "greaterThan":
+                    case "lessThan":
+                        console.log("Survey Element of type 'radio' cannot interpret contains/greaterThan/lessThan conditions. IGNORING");
+                        break;
+                    case "equals":
+                        if (node.response == condition.value) {
+                            pass = true;
+                        }
+                        break;
+                }
+                var jumpID;
+                if (pass) {
+                    jumpID = condition.jumpToOnPass;
+                } else {
+                    jumpID = condition.jumpToOnFail;
+                }
+                if (jumpID != undefined) {
+                    var index = this.popupOptions.findIndex(function(item,index,element){
+                        if (item.specification.id == jumpID) {return true;} else {return false;}
+                    },this);
+                    this.currentIndex = index-1;
+                    break;
+                }
+            }
 		} else if (node.specification.type == "number") {
 			var input = this.popupContent.getElementsByTagName('input')[0];
 			if (node.mandatory == true && input.value.length == 0) {
@@ -914,6 +1008,43 @@
 				return;
 			}
 			node.response = input.value;
+            // Perform the conditional
+            for (var condition of node.specification.conditions) {
+                var pass = false;
+                switch(condition.check) {
+                    case "contains":
+                        console.log("Survey Element of type 'number' cannot interpret contains conditions. IGNORING");
+                        break;
+                    case "greaterThan":
+                        if (node.response > Number(condition.value)) {
+                            pass = true;
+                        }
+                        break;
+                    case "lessThan":
+                        if (node.response < Number(condition.value)) {
+                            pass = true;
+                        }
+                        break;
+                    case "equals":
+                        if (node.response == condition.value) {
+                            pass = true;
+                        }
+                        break;
+                }
+                var jumpID;
+                if (pass) {
+                    jumpID = condition.jumpToOnPass;
+                } else {
+                    jumpID = condition.jumpToOnFail;
+                }
+                if (jumpID != undefined) {
+                    var index = this.popupOptions.findIndex(function(item,index,element){
+                        if (item.specification.id == jumpID) {return true;} else {return false;}
+                    },this);
+                    this.currentIndex = index-1;
+                    break;
+                }
+            }
 		}
 		this.currentIndex++;
 		if (this.currentIndex < this.popupOptions.length) {
@@ -3190,6 +3321,10 @@
 				surveyresult.appendChild(child);
 				break;
 			case "checkbox":
+                if (node.response == undefined) {
+                    surveyresult.appendChild(this.parent.document.createElement('response'));
+                    break;
+                }
 				for (var i=0; i<node.response.length; i++)
 				{
 					var checkNode = this.parent.document.createElement('response');
--- a/js/specification.js	Thu Jun 23 12:57:46 2016 +0100
+++ b/js/specification.js	Thu Jun 23 13:44:17 2016 +0100
@@ -214,6 +214,7 @@
 			this.min = undefined;
 			this.max = undefined;
 			this.step = undefined;
+            this.conditions = [];
 			
 			this.decode = function(parent,child)
 			{
@@ -252,6 +253,17 @@
 						}
 					}
 				}
+                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)
--- a/tests/examples/project.xml	Thu Jun 23 12:57:46 2016 +0100
+++ b/tests/examples/project.xml	Thu Jun 23 13:44:17 2016 +0100
@@ -4,6 +4,7 @@
 		<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>
@@ -13,6 +14,9 @@
 				<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>
--- a/xml/test-schema.xsd	Thu Jun 23 12:57:46 2016 +0100
+++ b/xml/test-schema.xsd	Thu Jun 23 13:44:17 2016 +0100
@@ -261,6 +261,7 @@
                                                 </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:complexType>