changeset 2857:80a3b693b3f6

More test_create work
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Thu, 27 Apr 2017 11:24:16 +0100
parents 5591d01adf1c
children cffde1e75b2d
files js/specification.js test_create.html test_create/test_core.js
diffstat 3 files changed, 695 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/js/specification.js	Wed Apr 26 17:48:35 2017 +0100
+++ b/js/specification.js	Thu Apr 27 11:24:16 2017 +0100
@@ -20,13 +20,20 @@
 
     // nodes
     this.metrics = new metricNode();
-    this.preTest = undefined;
-    this.postTest = undefined;
+    this.preTest = new surveyNode(this);
+    this.postTest = new surveyNode(this);
     this.pages = [];
     this.interfaces = new interfaceNode(this);
     this.errors = [];
     this.exitText = "Thank you.";
 
+    // Creators
+    this.createNewPage = function () {
+        var newpage = new page(this);
+        this.pages.push(newpage);
+        return newpage;
+    }
+
     var processAttribute = function (attribute, schema) {
         // attribute is the string returned from getAttribute on the XML
         // schema is the <xs:attribute> node
@@ -136,12 +143,10 @@
             switch (location) {
                 case 'pre':
                 case 'before':
-                    this.preTest = new surveyNode(this);
                     this.preTest.decode(this, survey[i]);
                     break;
                 case 'post':
                 case 'after':
-                    this.postTest = new surveyNode(this);
                     this.postTest.decode(this, survey[i]);
                     break;
             }
@@ -207,9 +212,14 @@
         this.location = undefined;
         this.options = [];
         this.parent = undefined;
-        this.schema = schemaRoot.querySelector('[name=survey]');
         this.specification = specification;
 
+        this.addOption = function () {
+            var node = new this.OptionNode(this.specification);
+            this.options.push(node);
+            return node;
+        }
+
         this.OptionNode = function (specification) {
             this.type = undefined;
             this.schema = undefined;
@@ -381,6 +391,7 @@
             };
         };
         this.decode = function (parent, xml) {
+            this.schema = schemaRoot.querySelector('[name=survey]');
             this.parent = parent;
             this.location = xml.getAttribute('location');
             if (this.location == 'before') {
@@ -540,8 +551,8 @@
         this.loudness = undefined;
         this.label = undefined;
         this.labelStart = undefined;
-        this.preTest = undefined;
-        this.postTest = undefined;
+        this.preTest = new surveyNode(specification);
+        this.postTest = new surveyNode(specification);
         this.interfaces = [];
         this.playOne = undefined;
         this.restrictMovement = undefined;
@@ -592,17 +603,15 @@
             for (i = 0; i < survey.length; i++) {
                 var location = survey[i].getAttribute('location');
                 if (location == 'pre' || location == 'before') {
-                    if (this.preTest !== undefined) {
+                    if (this.preTest.options.length !== 0) {
                         this.errors.push("Already a pre/before test survey defined! Ignoring second!!");
                     } else {
-                        this.preTest = new surveyNode(this.specification);
                         this.preTest.decode(parent, survey[i], surveySchema);
                     }
                 } else if (location == 'post' || location == 'after') {
-                    if (this.postTest !== undefined) {
+                    if (this.postTest.options.length !== 0) {
                         this.errors.push("Already a post/after test survey defined! Ignoring second!!");
                     } else {
-                        this.postTest = new surveyNode(this.specification);
                         this.postTest.decode(parent, survey[i], surveySchema);
                     }
                 }
--- a/test_create.html	Wed Apr 26 17:48:35 2017 +0100
+++ b/test_create.html	Thu Apr 27 11:24:16 2017 +0100
@@ -110,6 +110,7 @@
             </div>
             <div id="globalpresurvey" class="node">
                 <h2>Pre Test Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="specification.preTest.addOption()">Add Entry</button>
                 <div class="node" ng-repeat="opt in specification.preTest.options" ng-controller="surveyOption">
                     <h3>Survey Entry</h3>
                     <div class="attributes">
@@ -197,10 +198,49 @@
                             </div>
                         </div>
                     </div>
+                    <div class="node">
+                        <h4>Conditionals</h4>
+                        <button type="button" class="btn btn-default" ng-click="addCondition()">Add Condition</button>
+                        <div class="node" ng-repeat="condition in opt.conditions">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-danger" ng-click="removeCondition(condition)">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Check Type:</span>
+                                    <select ng-model="condition.check">
+                                        <option value="equals">Equal To</option>
+                                        <option value="lessThan">Less Than</option>
+                                        <option value="greaterThan">Greater Than</option>
+                                        <option value="stringContains">String Contains</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Value: </span>
+                                    <input type="text" ng-model="condition.value" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Pass: </span>
+                                    <select ng-model="condition.jumpToOnPass">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in specification.preTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Fail: </span>
+                                    <select ng-model="condition.jumpToOnFail">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in specification.preTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
                 </div>
             </div>
             <div id="globalpostsurvey" class="node">
                 <h2>Post Test Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="specification.postTest.addOption()">Add Entry</button>
                 <div class="node" ng-repeat="opt in specification.postTest.options" ng-controller="surveyOption">
                     <h3>Survey Entry</h3>
                     <div class="attributes">
@@ -288,6 +328,44 @@
                             </div>
                         </div>
                     </div>
+                    <div class="node">
+                        <h4>Conditionals</h4>
+                        <button type="button" class="btn btn-default" ng-click="addCondition()">Add Condition</button>
+                        <div class="node" ng-repeat="condition in opt.conditions">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-danger" ng-click="removeCondition(condition)">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Check Type:</span>
+                                    <select ng-model="condition.check">
+                                        <option value="equals">Equal To</option>
+                                        <option value="lessThan">Less Than</option>
+                                        <option value="greaterThan">Greater Than</option>
+                                        <option value="stringContains">String Contains</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Value: </span>
+                                    <input type="text" ng-model="condition.value" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Pass: </span>
+                                    <select ng-model="condition.jumpToOnPass">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in specification.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Fail: </span>
+                                    <select ng-model="condition.jumpToOnFail">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in specification.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
                 </div>
             </div>
             <div id="globalinterface" class="node" ng-controller="interfaceNode" ng-init="interface = specification.interfaces">
@@ -338,8 +416,567 @@
                 </div>
             </div>
         </div>
+        <div style="text-align: center;">
+            <button type="button" class="btn btn-success" ng-click="addPage()">Add Page</button>
+        </div>
         <div class="node pageNode" ng-controller="page" ng-repeat="page in specification.pages">
             <h2>Page</h2>
+            <div class="attributes">
+                <div class="attribute">
+                    <span>Unique ID: </span>
+                    <input type="text" ng-model="page.id" />
+                </div>
+                <div class="attribute">
+                    <span>Fragment common-root URL: </span>
+                    <input type="text" ng-model="page.hostURL" />
+                </div>
+                <div class="attribute">
+                    <span>Randomise Fragment Order: </span>
+                    <input type="checkbox" ng-model="page.randomiseOrder" />
+                </div>
+                <div class="attribute">
+                    <span>Repeat Page N-times: </span>
+                    <input type="number" ng-model="page.repeatCount" />
+                </div>
+                <div class="attribute">
+                    <span>Loop audio: </span>
+                    <input type="checkbox" ng-model="page.loop" />
+                </div>
+                <div class="attribute">
+                    <span>Synchronous audio playback: </span>
+                    <input type="checkbox" ng-model="page.synchronous" />
+                </div>
+                <div class="attribute">
+                    <span>Loudness (page): </span>
+                    <input type="number" ng-model="page.loudness" max="0" />
+                </div>
+                <div class="attribute">
+                    <span>Label type: </span>
+                    <select ng-model="page.label">
+                        <option value="default">Default</option>
+                        <option value="none">None</option>
+                        <option value="number">[1, 2, 3...]</option>
+                        <option value="letter">[a, b, c...]</option>
+                        <option value="capital">[A, B, C...]</option>
+                        <option value="samediff" ng-show="specification.interface == 'AB'">[Same, Different]</option>
+                    </select>
+                </div>
+                <div class="attribute" ng-show="page.label != 'default' && page.label != 'none'">
+                    <span>Label Start: </span>
+                    <input type="text" ng-model="page.labelStart" />
+                </div>
+                <div class="attribute">
+                    <span>Fragment pool size: </span>
+                    <input type="number" ng-model="page.poolSize" min="0" max="page.audioElements.length" />
+                </div>
+                <div class="attribute" ng-show="specification.poolSize > 0">
+                    <span>Always include page: </span>
+                    <input type="checkbox" ng-model="page.alwaysInclude" />
+                </div>
+                <div class="attribute">
+                    <span>Fixed Page Position: </span>
+                    <input type="number" ng-model="page.position" max="{{specification.pages.length}}" />
+                </div>
+                <div class="attribute">
+                    <span>Fixed Page Position: </span>
+                    <input type="number" ng-model="page.position" min="0" max="{{specification.pages.length}}" />
+                </div>
+                <div class="attribute">
+                    <span>Fragment pre-silence: </span>
+                    <input type="number" ng-model="page.preSilence" min="0" step="0.1" />
+                </div>
+                <div class="attribute">
+                    <span>Fragment post-silence: </span>
+                    <input type="number" ng-model="page.postSilence" min="0" step="0.1" />
+                </div>
+                <div class="attribute">
+                    <span>Cannot interupt audio: </span>
+                    <input type="checkbox" ng-model="page.playOne" />
+                </div>
+                <div class="attribute">
+                    <span>Only move playing audio: </span>
+                    <input type="checkbox" ng-model="page.restrictMovement" />
+                </div>
+            </div>
+            <div class="node">
+                <h3>Page Title</h3>
+                <textarea ng-model="page.title"></textarea>
+            </div>
+            <div class="node">
+                <h3>Comment box text prefix</h3>
+                <textarea ng-model="page.commentboxprefix"></textarea>
+                <p>Example:
+                    <span style="font-weight:600">{{page.commentboxprefix}} A</span>
+                </p>
+            </div>
+            <div class="node">
+                <h2>Pre Page Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="page.preTest.addOption()">Add Entry</button>
+                <div class="node" ng-repeat="opt in page.preTest.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <div class="attributes">
+                        <div class="attribute">
+                            <span>Survey Type: </span>
+                            <select ng-model="opt.type">
+                                <option value="question">Question</option>
+                                <option value="radio">Radio</option>
+                                <option value="checkbox">Checkbox</option>
+                                <option value="statement">Statement</option>
+                                <option value="number">Number</option>
+                                <option value="slider">Slider</option>
+                                <option value="video">Video</option>
+                                <option value="youtube">YouTube</option>
+                            </select>
+                        </div>
+                        <div class="attribute">
+                            <span>Unique Survey Entry ID:</span>
+                            <input type="text" ng-model="opt.id" />
+                        </div>
+                        <div class="attribute">
+                            <span>Entry Name:</span>
+                            <input type="text" ng-model="opt.name" />
+                        </div>
+                        <div class="attribute" ng-show="['question', 'checkbox', 'radio', 'number'].indexOf(opt.type) >= 0">
+                            <span>Mandatory:</span>
+                            <input type="checkbox" ng-model="opt.mandatory" />
+                        </div>
+                        <div class="attribute">
+                            <span>Minimum Wait Time (s):</span>
+                            <input type="number" ng-model="opt.minWait" min="0" />
+                        </div>
+                        <div class="attribute" ng-show="opt.type == 'question'">
+                            <span>Box Size:</span>
+                            <select ng-model="opt.boxsize">
+                                <option value="small">Small</option>
+                                <option value="normal">Normal</option>
+                                <option value="large">Large</option>
+                                <option value="huge">Huge</option>
+                            </select>
+                        </div>
+                        <div class="attribute" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                            <span>Minimum Selected:</span>
+                            <input type="number" ng-model="opt.min" min="0" />
+                        </div>
+                        <div class="attribute" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                            <span>Maximum Selected:</span>
+                            <input type="number" ng-model="opt.max" max="{{opt.options.length}}" />
+                        </div>
+                        <div class="attribute" ng-show="['slider', 'number'].indexOf(opt.type) >= 0">
+                            <span>Minimum Value:</span>
+                            <input type="number" ng-model="opt.min" />
+                        </div>
+                        <div class="attribute" ng-show="['slider', 'number'].indexOf(opt.type) >= 0">
+                            <span>Maximum Value:</span>
+                            <input type="number" ng-model="opt.max" />
+                        </div>
+                        <div class="attribute" ng-show="['video', 'youtube'].indexOf(opt.type) >= 0">
+                            <span>Video URL:</span>
+                            <input type="text" ng-model="opt.url" />
+                        </div>
+                    </div>
+                    <div class="node">
+                        <h4>Statement</h4>
+                        <textarea ng-model="opt.statement"></textarea>
+                    </div>
+                    <div class="node" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                        <h4>Options</h4>
+                        <div>
+                            <button type="button" class="btn btn-default" ng-click="addOption();">Add Option</button>
+                        </div>
+                        <div class="node" ng-repeat="option in opt.options">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-default" ng-click="removeOption(option);">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Name: </span>
+                                    <input type="text" ng-model="option.name" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Displayed Text: </span>
+                                    <input type="text" ng-model="option.text" />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="node">
+                        <h4>Conditionals</h4>
+                        <button type="button" class="btn btn-default" ng-click="addCondition()">Add Condition</button>
+                        <div class="node" ng-repeat="condition in opt.conditions">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-danger" ng-click="removeCondition(condition)">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Check Type:</span>
+                                    <select ng-model="condition.check">
+                                        <option value="equals">Equal To</option>
+                                        <option value="lessThan">Less Than</option>
+                                        <option value="greaterThan">Greater Than</option>
+                                        <option value="stringContains">String Contains</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Value: </span>
+                                    <input type="text" ng-model="condition.value" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Pass: </span>
+                                    <select ng-model="condition.jumpToOnPass">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in page.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Fail: </span>
+                                    <select ng-model="condition.jumpToOnFail">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in page.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="node">
+                <h2>Post Page Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="page.postTest.addOption()">Add Entry</button>
+                <div class="node" ng-repeat="opt in page.postTest.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <div class="attributes">
+                        <div class="attribute">
+                            <span>Survey Type: </span>
+                            <select ng-model="opt.type">
+                                <option value="question">Question</option>
+                                <option value="radio">Radio</option>
+                                <option value="checkbox">Checkbox</option>
+                                <option value="statement">Statement</option>
+                                <option value="number">Number</option>
+                                <option value="slider">Slider</option>
+                                <option value="video">Video</option>
+                                <option value="youtube">YouTube</option>
+                            </select>
+                        </div>
+                        <div class="attribute">
+                            <span>Unique Survey Entry ID:</span>
+                            <input type="text" ng-model="opt.id" />
+                        </div>
+                        <div class="attribute">
+                            <span>Entry Name:</span>
+                            <input type="text" ng-model="opt.name" />
+                        </div>
+                        <div class="attribute" ng-show="['question', 'checkbox', 'radio', 'number'].indexOf(opt.type) >= 0">
+                            <span>Mandatory:</span>
+                            <input type="checkbox" ng-model="opt.mandatory" />
+                        </div>
+                        <div class="attribute">
+                            <span>Minimum Wait Time (s):</span>
+                            <input type="number" ng-model="opt.minWait" min="0" />
+                        </div>
+                        <div class="attribute" ng-show="opt.type == 'question'">
+                            <span>Box Size:</span>
+                            <select ng-model="opt.boxsize">
+                                <option value="small">Small</option>
+                                <option value="normal">Normal</option>
+                                <option value="large">Large</option>
+                                <option value="huge">Huge</option>
+                            </select>
+                        </div>
+                        <div class="attribute" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                            <span>Minimum Selected:</span>
+                            <input type="number" ng-model="opt.min" min="0" />
+                        </div>
+                        <div class="attribute" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                            <span>Maximum Selected:</span>
+                            <input type="number" ng-model="opt.max" max="{{opt.options.length}}" />
+                        </div>
+                        <div class="attribute" ng-show="['slider', 'number'].indexOf(opt.type) >= 0">
+                            <span>Minimum Value:</span>
+                            <input type="number" ng-model="opt.min" />
+                        </div>
+                        <div class="attribute" ng-show="['slider', 'number'].indexOf(opt.type) >= 0">
+                            <span>Maximum Value:</span>
+                            <input type="number" ng-model="opt.max" />
+                        </div>
+                        <div class="attribute" ng-show="['video', 'youtube'].indexOf(opt.type) >= 0">
+                            <span>Video URL:</span>
+                            <input type="text" ng-model="opt.url" />
+                        </div>
+                    </div>
+                    <div class="node">
+                        <h4>Statement</h4>
+                        <textarea ng-model="opt.statement"></textarea>
+                    </div>
+                    <div class="node" ng-show="['checkbox', 'radio'].indexOf(opt.type) >= 0">
+                        <h4>Options</h4>
+                        <div>
+                            <button type="button" class="btn btn-default" ng-click="addOption();">Add Option</button>
+                        </div>
+                        <div class="node" ng-repeat="option in opt.options">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-default" ng-click="removeOption(option);">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Name: </span>
+                                    <input type="text" ng-model="option.name" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Displayed Text: </span>
+                                    <input type="text" ng-model="option.text" />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="node">
+                        <h4>Conditionals</h4>
+                        <button type="button" class="btn btn-default" ng-click="addCondition()">Add Condition</button>
+                        <div class="node" ng-repeat="condition in opt.conditions">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-danger" ng-click="removeCondition(condition)">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Check Type:</span>
+                                    <select ng-model="condition.check">
+                                        <option value="equals">Equal To</option>
+                                        <option value="lessThan">Less Than</option>
+                                        <option value="greaterThan">Greater Than</option>
+                                        <option value="stringContains">String Contains</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Value: </span>
+                                    <input type="text" ng-model="condition.value" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Pass: </span>
+                                    <select ng-model="condition.jumpToOnPass">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in page.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                                <div class="attribute">
+                                    <span>Jump To On Fail: </span>
+                                    <select ng-model="condition.jumpToOnFail">
+                                        <option value="">None</option>
+                                        <option ng-repeat="entry in page.postTest.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="node" ng-repeat="interface in page.interfaces" ng-controller="interfaceNode">
+                <h2>Interface</h2>
+                <div class="node interfaceOptions">
+                    <div class="attributes">
+                        <div class="attribute" name="fragmentPlayed" type="check">
+                            <span>Check all fragments played: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="fragmentFullPlayback" type="check">
+                            <span>Check all fragments fully played: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="fragmentMoved" type="check">
+                            <span>Check all fragments have been moved: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="fragmentComments" type="check">
+                            <span>Check all fragments have comments: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="scalerange" type="check">
+                            <span>Enforce a scale usage: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                            <span>Minimum:</span>
+                            <input type="number" min="0" max="100" name="min" />
+                            <span>Maximum:</span>
+                            <input type="number" min="0" max="100" name="max" />
+                        </div>
+                        <div class="attribute" name="volume" type="show">
+                            <span>Show master volume control: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="playhead" type="show">
+                            <span>Show playhead: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="page-count" type="show">
+                            <span>Show Page Count: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                        <div class="attribute" name="comments" type="show">
+                            <span>Show Fragment Comments: </span>
+                            <input type="checkbox" ng-click="enableInterfaceOption($event)" />
+                        </div>
+                    </div>
+                </div>
+                <div class="node">
+                    <h3>Axis Title</h3>
+                    <textarea ng-model="interface.title"></textarea>
+                    <div class="attributes">
+                        <div class="attribute">
+                            <span>Axis name (in saves): </span>
+                            <input type="text" ng-model="interface.name" />
+                        </div>
+                    </div>
+                </div>
+                <div class="node">
+                    <h3>Axis Image</h3>
+                    <textarea ng-model="interface.image"></textarea>
+                </div>
+                <div class="node">
+                    <h3>Axis Scales</h3>
+                    <button type="button" class="btn btn-default" ng-click="addScale();">Add</button>
+                    <div class="node" ng-repeat="scale in interface.scales">
+                        <div class="attributes">
+                            <div class="attribute">
+                                <button type="button" class="btn btn-danger" ng-click="removeScale(scale);">Remove</button>
+                            </div>
+                            <div class="attribute">
+                                <span>Position: </span>
+                                <input type="number" min="0" max="100" ng-model="scale.position" />
+                            </div>
+                            <div class="attribute">
+                                <span>Text: </span>
+                                <input type="text" ng-model="scale.text" />
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="node">
+                <h3>Comment Questions</h3>
+                <div class="node" ng-repeat="cq in page.commentQuestions">
+                    <div class="attributes">
+                        <div class="attribute">
+                            <span>Unique ID:</span>
+                            <input type="text" ng-model="cq.id" />
+                        </div>
+                        <div class="attribute">
+                            <span>Common Name:</span>
+                            <input type="text" ng-model="cq.name" />
+                        </div>
+                        <div class="attribute" ng-show="cq.type == 'slider'">
+                            <span>Minimum:</span>
+                            <input type="number" ng-model="cq.min" />
+                        </div>
+                        <div class="attribute" ng-show="cq.type == 'slider'">
+                            <span>Maximum:</span>
+                            <input type="number" ng-model="cq.max" />
+                        </div>
+                        <div class="attribute" ng-show="cq.type == 'slider'">
+                            <span>Step size:</span>
+                            <input type="number" ng-model="cq.step" />
+                        </div>
+                        <div class="attribute" ng-show="cq.type == 'slider'">
+                            <span>Initial Value:</span>
+                            <input type="number" ng-model="cq.value" />
+                        </div>
+                    </div>
+                    <div class="node">
+                        <h4>Question:</h4>
+                        <textarea ng-model="cq.statement"></textarea>
+                    </div>
+                    <div class="node" ng-show="['radio', 'checkbox'].indexOf(cq.type) >= 0">
+                        <h4>Options</h4>
+                        <div class="node" ng-repeat="option in cq.options">
+                            <div class="attributes">
+                                <div class="attribute">
+                                    <button type="button" class="btn btn-danger" ng-click="removeCommentQuestionOption(cq,option)">Remove</button>
+                                </div>
+                                <div class="attribute">
+                                    <span>Name: </span>
+                                    <input type="text" ng-model="option.name" />
+                                </div>
+                                <div class="attribute">
+                                    <span>Display Text: </span>
+                                    <input type="text" ng-model="option.text" />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="node" ng-repeat="fragment in page.audioElements">
+                <h3>Audio Fragment</h3>
+                <div class="attributes">
+                    <div class="attribute">
+                        <span>Unique ID: </span>
+                        <input type="text" ng-model="fragment.id" />
+                    </div>
+                    <div class="attribute">
+                        <span>URL: </span>
+                        <input type="text" ng-model="fragment.url" />
+                        <span>Full URL: </span><span style="font-weight=600">{{page.hostURL}}{{fragment.url}}</span>
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Gain (dB): </span>
+                        <input type="number" ng-model="fragment.gain" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Label: </span>
+                        <input type="text" ng-model="fragment.label" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Common name: </span>
+                        <input type="text" ng-model="fragment.name" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Type: </span>
+                        <select ng-model="fragment.type">
+                            <option value="normal">Normal</option>
+                            <option value="anchor">Hidden Anchor</option>
+                            <option value="reference">Hidden Reference</option>
+                            <option value="outside-reference">Outside Reference</option>
+                        </select>
+                    </div>
+                    <div class="attribute" ng-show="fragment.type == 'anchor'">
+                        <span>Anchor must be below: </span>
+                        <input type="number" ng-model="fragment.marker" min="0" max="100" />
+                    </div>
+                    <div class="attribute" ng-show="fragment.type == 'reference'">
+                        <span>Reference must be above: </span>
+                        <input type="number" ng-model="fragment.marker" min="0" max="100" />
+                    </div>
+                    <div class="attribute">
+                        <span>Loudness: </span>
+                        <input type="number" ng-model="fragment.loudness" max="0" />
+                    </div>
+                    <div class="attribute" ng-show="page.poolSize > 0">
+                        <span>Always include fragment: </span>
+                        <input type="checkbox" ng-model="fragment.alwaysInclude" max="0" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Pre-Silence: </span>
+                        <input type="number" ng-model="fragment.preSilence" max="0" step="0.1" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Post-Silence: </span>
+                        <input type="number" ng-model="fragment.postSilence" max="0" step="0.1" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment playback start position (s): </span>
+                        <input type="number" ng-model="fragment.startTime" min="0" max="{{fragment.stopTime}}" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment playback stop position (s): </span>
+                        <input type="number" ng-model="fragment.stopTime" min="{{fragment.startTime}}" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment sampling rate: </span>
+                        <input type="number" ng-model="fragment.sampleRate" min="1" />
+                    </div>
+                    <div class="attribute">
+                        <span>Fragment Image (URL): </span>
+                        <input type="text" ng-model="fragment.image" />
+                    </div>
+                </div>
+            </div>
         </div>
         <div id="popupHolder" ng-show="popupVisible">
             <div ng-controller="introduction" class="popup" ng-show="popupVisible">
--- a/test_create/test_core.js	Wed Apr 26 17:48:35 2017 +0100
+++ b/test_create/test_core.js	Thu Apr 27 11:24:16 2017 +0100
@@ -53,6 +53,10 @@
         $s.globalSchema = specification.getSchema();
     });
     $s.specification = specification;
+
+    $s.addPage = function () {
+        $s.specification.createNewPage();
+    }
 }]);
 
 AngularInterface.controller("introduction", ['$scope', '$element', '$window', function ($s, $e, $w) {
@@ -163,6 +167,25 @@
             text: ""
         });
     };
+
+    $s.addCondition = function () {
+        $s.opt.conditions.push({
+            check: "equals",
+            value: "",
+            jumpToOnPass: undefined,
+            jumpToOnFail: undefined
+        });
+    };
+
+    $s.removeCondition = function (condition) {
+        var index = $s.opt.conditions.findIndex(function (c) {
+            return c == condition;
+        });
+        if (index === -1) {
+            throw ("Invalid Condition");
+        }
+        $s.opt.conditions.splice(index, 1);
+    };
 }]);
 
 AngularInterface.controller("interfaceNode", ['$scope', '$element', '$window', function ($s, $e, $w) {
@@ -201,6 +224,20 @@
         } else if (index >= 0 && !$event.currentTarget.checked) {
             $s.interface.options.splice(index, 1);
         }
-    }
+    };
+    $s.removeScale = function (scale) {
+        var index = $s.interface.scales.findIndex(function (s) {
+            return s == scale;
+        });
+        if (index >= 0) {
+            $s.interface.scales.splice(index, 1);
+        }
+    };
+    $s.addScale = function () {
+        $s.interface.scales.push({
+            position: undefined,
+            text: undefined
+        });
+    };
 }]);
 AngularInterface.controller("page", ['$scope', '$element', '$window', function ($s, $e, $w) {}]);