changeset 2859:d432bf25889b

Finalised test_create UI
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Thu, 27 Apr 2017 12:02:28 +0100
parents cffde1e75b2d
children 65b8d9ad75cc
files js/specification.js test_create.html test_create/test_core.js
diffstat 3 files changed, 1096 insertions(+), 1034 deletions(-) [+]
line wrap: on
line diff
--- a/js/specification.js	Thu Apr 27 11:43:08 2017 +0100
+++ b/js/specification.js	Thu Apr 27 12:02:28 2017 +0100
@@ -32,7 +32,7 @@
         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
@@ -218,7 +218,7 @@
             var node = new this.OptionNode(this.specification);
             this.options.push(node);
             return node;
-        }
+        };
 
         this.OptionNode = function (specification) {
             this.type = undefined;
@@ -419,7 +419,7 @@
             }
             return node;
         };
-    };
+    }
 
     function interfaceNode(specification) {
         this.title = undefined;
@@ -513,7 +513,7 @@
             }
             return node;
         };
-    };
+    }
 
     function metricNode() {
         this.enabled = [];
@@ -538,7 +538,7 @@
             }
             return node;
         };
-    };
+    }
 
     function page(specification) {
         this.presentedId = undefined;
@@ -564,6 +564,22 @@
         this.specification = specification;
         this.parent = undefined;
 
+        this.addInterface = function () {
+            var node = new interfaceNode(specification);
+            this.interfaces.push(node);
+            return node;
+        };
+        this.addCommentQuestion = function () {
+            var node = new commentQuestionNode(specification);
+            this.commentQuestions.push(node);
+            return node;
+        };
+        this.addAudioElement = function () {
+            var node = new audioElementNode(specification);
+            this.audioElements.push(node);
+            return node;
+        };
+
         this.decode = function (parent, xml) {
             this.parent = parent;
             var attributeMap = this.schema.querySelectorAll('attribute');
@@ -801,7 +817,7 @@
                 }
                 return node;
             };
-        };
+        }
 
         function audioElementNode(specification) {
             this.url = undefined;
@@ -864,6 +880,6 @@
                 });
                 return AENode;
             };
-        };
-    };
+        }
+    }
 }
--- a/test_create.html	Thu Apr 27 11:43:08 2017 +0100
+++ b/test_create.html	Thu Apr 27 12:02:28 2017 +0100
@@ -1,1024 +1,1032 @@
-<html>
-
-<head>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8">
-    <!-- This defines the test creator tool for the Web Audio Evaluation Toolbox -->
-    <link rel="stylesheet" type="text/css" href="test_create/style.css" />
-    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
-    <script src="js/jquery-2.1.4.js"></script>
-    <script src="js/angular.min.js"></script>
-    <script type="text/javascript" src="js/specification.js"></script>
-    <script type="text/javascript" src="test_create/test_core.js"></script>
-    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
-
-    <title>WAET 1.2.1 Test Creator</title>
-</head>
-
-<body>
-    <div ng-app="creator" ng-controller="view">
-        <div id="pageRoot">
-            <h1>Web Audio Evaluation Tool - Test Creator</h1>
-        </div>
-        <div id="setupNode" class="node" ng-controller="setup">
-            <h2>Setup</h2>
-            <div class="attributes">
-                <div class="attribute">
-                    <span>Interface: </span>
-                    <input type="text" ng-model="specification.interface" />
-                </div>
-                <div class="attribute">
-                    <span>Save URL: </span>
-                    <input type="text" ng-model="specification.projectReturn" />
-                </div>
-                <div class="attribute">
-                    <span>Exit URL: </span>
-                    <input type="text" ng-model="specification.returnURL" />
-                </div>
-                <div class="attribute">
-                    <span>Randomise Page Order: </span>
-                    <input type="checkbox" ng-model="specification.randomiseOrder" />
-                </div>
-                <div class="attribute">
-                    <span>Page Pool Size: </span>
-                    <input type="number" ng-model="specification.poolSize" min="0" />
-                </div>
-                <div class="attribute">
-                    <span>Loudness Normalisation (LUFS): </span>
-                    <input type="number" ng-model="specification.loudness" max="0" />
-                </div>
-                <div class="attribute">
-                    <span>Fixed Sampling Rate: </span>
-                    <input type="number" ng-model="specification.sampleRate" min="0" />
-                </div>
-                <div class="attribute">
-                    <span>Pre-Test audio calibration: </span>
-                    <input type="checkbox" ng-model="specification.calibration" />
-                </div>
-                <div class="attribute">
-                    <span>Global Cross-fade time: </span>
-                    <input type="number" ng-model="specification.crossFade" min="0" step="0.1" />
-                </div>
-                <div class="attribute">
-                    <span>Global Fragment Pre-Silence: </span>
-                    <input type="number" ng-model="specification.preSilence" min="0" step="0.1" />
-                </div>
-                <div class="attribute">
-                    <span>Global Fragment Post-Silence: </span>
-                    <input type="number" ng-model="specification.preSilence" min="0" step="0.1" />
-                </div>
-                <div class="attribute">
-                    <span>Play audio one-at-a-time: </span>
-                    <input type="checkbox" ng-model="specification.playOne" />
-                </div>
-            </div>
-            <div class="node">
-                <h2>Test Completed Message</h2>
-                <textarea ng-model="specification.exitText"></textarea>
-            </div>
-            <div id="metricsNode" class="node">
-                <h3>Session Metrics</h3>
-                <div class="attributes">
-                    <div class="attribute">
-                        <span>Collect Total Test Time: </span>
-                        <input type="checkbox" value="testTimer" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Listen Time: </span>
-                        <input type="checkbox" value="elementTimer" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Initial Position: </span>
-                        <input type="checkbox" value="elementInitialPosition" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Position over Time: </span>
-                        <input type="checkbox" value="elementTracker" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Listened To Flag: </span>
-                        <input type="checkbox" value="elementFlagListenedTo" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Moved Flag: </span>
-                        <input type="checkbox" value="elementFlagMoved" ng-click="enableMetric($event)" />
-                    </div>
-                    <div class="attribute">
-                        <span>Collect Fragment Listened Flag: </span>
-                        <input type="checkbox" value="elementListenTracker" ng-click="enableMetric($event)" />
-                    </div>
-                </div>
-            </div>
-            <div id="globalpresurvey" class="node" ng-controller="survey" ng-init="survey = specification.preTest">
-                <h2>Pre Test Survey</h2>
-                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
-                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
-                    <h3>Survey Entry</h3>
-                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
-                    <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 survey.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 survey.options" value="{{entry.id}}">{{entry.id}}</option>
-                                    </select>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <div id="globalpostsurvey" class="node" ng-controller="survey" ng-init="survey = specification.postTest">
-                <h2>Post Test Survey</h2>
-                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
-                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
-                    <h3>Survey Entry</h3>
-                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
-                    <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 survey.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 survey.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">
-                <h2>Interface (Globals)</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>
-        </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">
-                <div class="popupTitle" ng-switch="state">
-                    <span ng-switch-when="0">Test Creator</span>
-                    <span ng-switch-when="1">Create New Test</span>
-                </div>
-                <div class="popupContent container-fluid" ng-switch="state">
-                    <div ng-switch-when="0">
-                        <div>
-                            <span>Welcome to the WAET test creator tool. This will allow you to create a new test from scratch to suit your testing needs. If you wish to update a test file, please drag and drop the XML document into the area below for processing, otherwise press 'Next' to start a new test. This tool generates files for the WAET 1.2.1 version.</span>
-                        </div>
-                        <div class="drag-drop" id="introdragdrop"><span>Upload XML here</span></div>
-                    </div>
-                    <div ng-switch-when="1">
-                        <div>
-                            <span>Please select the interface you would like to use below. Selecting an interface will give a brief description of the interface type.</span>
-                        </div>
-                        <div class="row">
-                            <div class="col-md-6" style="overflow-y: scroll;height: 333px;">
-                                <div class="new-test" ng-repeat="i in interfaces" ng-mouseover="mouseover(i.name)" ng-click="initialise(i.name)">
-                                    <label style="cursor:pointer">
-                                        <input type="radio" name="new-test" value="{{i.name}}" id="i.name" style="cursor:pointer" /> {{i.name}}
-                                    </label>
-                                </div>
-                            </div>
-                            <div class="col-md-6">
-                                <span>{{description}}</span>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-                <div class="popupButtons">
-                    <button id="popupBack" type="button" class="btn btn-default" ng-show="state>0" ng-click="back()">Back</button>
-                    <button id="popupNext" type="button" class="btn btn-default" ng-click="next()">Next</button>
-                </div>
-            </div>
-        </div>
-        <div id="screenblank" ng-show="popupVisible"></div>
-    </div>
-</body>
-
-</html>
+<html>
+
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <!-- This defines the test creator tool for the Web Audio Evaluation Toolbox -->
+    <link rel="stylesheet" type="text/css" href="test_create/style.css" />
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+    <script src="js/jquery-2.1.4.js"></script>
+    <script src="js/angular.min.js"></script>
+    <script type="text/javascript" src="js/specification.js"></script>
+    <script type="text/javascript" src="test_create/test_core.js"></script>
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
+
+    <title>WAET 1.2.1 Test Creator</title>
+</head>
+
+<body>
+    <div ng-app="creator" ng-controller="view">
+        <div id="pageRoot">
+            <h1>Web Audio Evaluation Tool - Test Creator</h1>
+        </div>
+        <div id="setupNode" class="node" ng-controller="setup">
+            <h2>Setup</h2>
+            <div class="attributes">
+                <div class="attribute">
+                    <span>Interface: </span>
+                    <input type="text" ng-model="specification.interface" />
+                </div>
+                <div class="attribute">
+                    <span>Save URL: </span>
+                    <input type="text" ng-model="specification.projectReturn" />
+                </div>
+                <div class="attribute">
+                    <span>Exit URL: </span>
+                    <input type="text" ng-model="specification.returnURL" />
+                </div>
+                <div class="attribute">
+                    <span>Randomise Page Order: </span>
+                    <input type="checkbox" ng-model="specification.randomiseOrder" />
+                </div>
+                <div class="attribute">
+                    <span>Page Pool Size: </span>
+                    <input type="number" ng-model="specification.poolSize" min="0" />
+                </div>
+                <div class="attribute">
+                    <span>Loudness Normalisation (LUFS): </span>
+                    <input type="number" ng-model="specification.loudness" max="0" />
+                </div>
+                <div class="attribute">
+                    <span>Fixed Sampling Rate: </span>
+                    <input type="number" ng-model="specification.sampleRate" min="0" />
+                </div>
+                <div class="attribute">
+                    <span>Pre-Test audio calibration: </span>
+                    <input type="checkbox" ng-model="specification.calibration" />
+                </div>
+                <div class="attribute">
+                    <span>Global Cross-fade time: </span>
+                    <input type="number" ng-model="specification.crossFade" min="0" step="0.1" />
+                </div>
+                <div class="attribute">
+                    <span>Global Fragment Pre-Silence: </span>
+                    <input type="number" ng-model="specification.preSilence" min="0" step="0.1" />
+                </div>
+                <div class="attribute">
+                    <span>Global Fragment Post-Silence: </span>
+                    <input type="number" ng-model="specification.preSilence" min="0" step="0.1" />
+                </div>
+                <div class="attribute">
+                    <span>Play audio one-at-a-time: </span>
+                    <input type="checkbox" ng-model="specification.playOne" />
+                </div>
+            </div>
+            <div class="node">
+                <h2>Test Completed Message</h2>
+                <textarea ng-model="specification.exitText"></textarea>
+            </div>
+            <div id="metricsNode" class="node">
+                <h3>Session Metrics</h3>
+                <div class="attributes">
+                    <div class="attribute">
+                        <span>Collect Total Test Time: </span>
+                        <input type="checkbox" value="testTimer" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Listen Time: </span>
+                        <input type="checkbox" value="elementTimer" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Initial Position: </span>
+                        <input type="checkbox" value="elementInitialPosition" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Position over Time: </span>
+                        <input type="checkbox" value="elementTracker" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Listened To Flag: </span>
+                        <input type="checkbox" value="elementFlagListenedTo" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Moved Flag: </span>
+                        <input type="checkbox" value="elementFlagMoved" ng-click="enableMetric($event)" />
+                    </div>
+                    <div class="attribute">
+                        <span>Collect Fragment Listened Flag: </span>
+                        <input type="checkbox" value="elementListenTracker" ng-click="enableMetric($event)" />
+                    </div>
+                </div>
+            </div>
+            <div id="globalpresurvey" class="node" ng-controller="survey" ng-init="survey = specification.preTest">
+                <h2>Pre Test Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
+                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
+                    <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 survey.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 survey.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div id="globalpostsurvey" class="node" ng-controller="survey" ng-init="survey = specification.postTest">
+                <h2>Post Test Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
+                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
+                    <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 survey.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 survey.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">
+                <h2>Interface (Globals)</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>
+        </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" ng-controller="survey" ng-init="survey = page.preTest">
+                <h2>Pre Page Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
+                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
+                    <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 survey.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 survey.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="node" ng-controller="survey" ng-init="survey = specification.postTest">
+                <h2>Post Page Survey</h2>
+                <button type="button" class="btn btn-success" ng-click="addSurveyEntry()">Add Entry</button>
+                <div class="node" ng-repeat="opt in survey.options" ng-controller="surveyOption">
+                    <h3>Survey Entry</h3>
+                    <button type="button" class="btn btn-danger" ng-click="removeSurveyEntry(opt);">Delete Entry</button>
+                    <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 survey.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 survey.options" value="{{entry.id}}">{{entry.id}}</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <button type="button" class="btn btn-success" ng-show="specification.interface == 'APE' || page.interfaces.length == 0" ng-click="addInterface()">Add Interface/Axis</button>
+            <div class="node" ng-repeat="interface in page.interfaces" ng-controller="interfaceNode">
+                <h2>Interface</h2>
+                <button type="button" class="btn btn-danger" ng-click="removeInterface(interface)">Remove Interface/Axis</button>
+                <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>
+                <button type="button" class="btn btn-success" ng-click="addCommentQuestion()">Add Comment Question</button>
+                <div class="node" ng-repeat="cq in page.commentQuestions">
+                    <button type="button" class="btn btn-danger" ng-click="removeCommentQuestion(cq)">Remove Comment Question</button>
+                    <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>
+            <button type="button" class="btn btn-success" ng-click="addAudioElement()">Add Fragment</button>
+            <div class="node" ng-repeat="fragment in page.audioElements">
+                <h3>Audio Fragment</h3>
+                <button type="button" class="btn btn-danger" ng-click="removeAudioElement(fragment)">Remove Fragment</button>
+                <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">
+                <div class="popupTitle" ng-switch="state">
+                    <span ng-switch-when="0">Test Creator</span>
+                    <span ng-switch-when="1">Create New Test</span>
+                </div>
+                <div class="popupContent container-fluid" ng-switch="state">
+                    <div ng-switch-when="0">
+                        <div>
+                            <span>Welcome to the WAET test creator tool. This will allow you to create a new test from scratch to suit your testing needs. If you wish to update a test file, please drag and drop the XML document into the area below for processing, otherwise press 'Next' to start a new test. This tool generates files for the WAET 1.2.1 version.</span>
+                        </div>
+                        <div class="drag-drop" id="introdragdrop"><span>Upload XML here</span></div>
+                    </div>
+                    <div ng-switch-when="1">
+                        <div>
+                            <span>Please select the interface you would like to use below. Selecting an interface will give a brief description of the interface type.</span>
+                        </div>
+                        <div class="row">
+                            <div class="col-md-6" style="overflow-y: scroll;height: 333px;">
+                                <div class="new-test" ng-repeat="i in interfaces" ng-mouseover="mouseover(i.name)" ng-click="initialise(i.name)">
+                                    <label style="cursor:pointer">
+                                        <input type="radio" name="new-test" value="{{i.name}}" id="i.name" style="cursor:pointer" /> {{i.name}}
+                                    </label>
+                                </div>
+                            </div>
+                            <div class="col-md-6">
+                                <span>{{description}}</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="popupButtons">
+                    <button id="popupBack" type="button" class="btn btn-default" ng-show="state>0" ng-click="back()">Back</button>
+                    <button id="popupNext" type="button" class="btn btn-default" ng-click="next()">Next</button>
+                </div>
+            </div>
+        </div>
+        <div id="screenblank" ng-show="popupVisible"></div>
+    </div>
+</body>
+
+</html>
--- a/test_create/test_core.js	Thu Apr 27 11:43:08 2017 +0100
+++ b/test_create/test_core.js	Thu Apr 27 12:02:28 2017 +0100
@@ -56,7 +56,7 @@
 
     $s.addPage = function () {
         $s.specification.createNewPage();
-    }
+    };
 }]);
 
 AngularInterface.controller("introduction", ['$scope', '$element', '$window', function ($s, $e, $w) {
@@ -255,4 +255,42 @@
         });
     };
 }]);
-AngularInterface.controller("page", ['$scope', '$element', '$window', function ($s, $e, $w) {}]);
+AngularInterface.controller("page", ['$scope', '$element', '$window', function ($s, $e, $w) {
+    $s.addInterface = function () {
+        $s.page.addInterface();
+    };
+    $s.removeInterface = function (node) {
+        var index = $s.page.interfaces.findIndex(function (a) {
+            return a == node;
+        });
+        if (index === -1) {
+            throw ("Invalid node");
+        }
+        $s.page.interfaces.splice(index, 1);
+    };
+
+    $s.addCommentQuestion = function () {
+        $s.page.addCommentQuestion();
+    };
+    $s.removeCommentQuestion = function (node) {
+        var index = $s.page.commentQuestions.findIndex(function (a) {
+            return a == node;
+        });
+        if (index === -1) {
+            throw ("Invalid node");
+        }
+        $s.page.commentQuestions.splice(index, 1);
+    };
+    $s.addAudioElement = function () {
+        $s.page.addAudioElement();
+    };
+    $s.removeAudioElement = function (element) {
+        var index = $s.page.audioElements.findIndex(function (a) {
+            return a == element;
+        });
+        if (index === -1) {
+            throw ("Invalid node");
+        }
+        $s.page.audioElements.splice(index, 1);
+    };
+}]);