Index: Dev/trunk/js/sequencerScripts.js
===================================================================
--- Dev/trunk/js/sequencerScripts.js	(revision 182)
+++ Dev/trunk/js/sequencerScripts.js	(revision 183)
@@ -15,4 +15,12 @@
         }
     },
+    survey: {               // Properties of the loaded survey, if applicable (either this or the session tree above is filled in!) [THIS IS NOT CURRENTLY USED AND I SHOULD DELIBERATE ON WHAT VARIABLES TO PUT IN THIS TREE TO MAKE A FUNCTIONAL EDITOR THAT ALSO MATCHES THE DB FORMAT!]
+        title: "",              // Title or the name of the survey
+        uid: "",                // Uid of the survey
+        questions: {            // Properties of the questions contained within this survey
+            uids: [],               // An array of uids of the questions, in the order that they appear in the survey
+            upToDate: []            // Whether or not a certain question needs an update
+        }
+    },
     state: {                // Operating state of the sequencer
         editing: false,         // Whether or not one of the contained child objects is currently being edited or in edit mode. Which one can be determined from the selectedStep property.
@@ -21,10 +29,10 @@
         selectedStep: {         // Properties of the currently selected step
             uid: "",                // UID of this step (STRING)
-            index: null               // The 'index' of this step in the current sequencer view (NOT the pipeline!) (INTEGER)
+            index: null             // The 'index' of this step in the current sequencer view (NOT the pipeline!) (INTEGER)
         }        
     },
     settings: {             // Various settings to determine the workings of the sequencer
         content: {              // Properties related to the content view of the sequencer
-            contentType: "session", // Type of the loaded parent object
+            contentType: "session", // Type of the loaded parent object (STRING)
             width: null,            // Width of the viewing area (INTEGER)
             height: null,           // Height of the viewing area (INTEGER)
@@ -139,76 +147,89 @@
 
     /*
- * Description:
- * This function updates the visual elements in the sequencer content view to match the current state of the sequencer.session.pipeline property.
- * It queries the database for object properties via AJAX (returnStep/Display/.php), then inserts divider div's in between where needed.
- */
+     * Description:
+     * This function updates the visual elements in the sequencer content view to match the current state of the sequencer.session.pipeline property.
+     * It queries the database for object properties via AJAX (returnStep/Display/.php), then inserts divider div's in between where needed.
+     */
     var content = document.getElementById("seqContentWrapper");
+    var requestString, needsUpdating;
+    var args;
     if (sequencer.state.loaded == false || sequencer.settings.efficientUpdating == false) {  // This is the first update of the sequencer since page load, therefore it contains no previous steps
+        // Stop running this function if the pipeline does not contain any elements to draw
+        if (sequencer.session.pipeline.uids.length == 0 || !sequencer.session.pipeline.uids.length) return;
         // First clear the entire content wrapper, just for safety and in case efficientUpdating is off
         while (content.firstChild) {
             content.removeChild(content.firstChild);
         }
-        // Compose a request string - "uids=1,2,3&types=a,b,c"
-        var requestString = "uids=";
+        args = [];
+        needsUpdating = [];
         for (var i = 0; i < sequencer.session.pipeline.uids.length; i++) {
-            requestString += sequencer.session.pipeline.uids[i]+",";
-            sequencer.state.numSteps++;
-        }
-        
-        requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
-        requestString += "&types=";
-        for (var j = 0; j < sequencer.session.pipeline.types.length; j++) {
-            requestString += sequencer.session.pipeline.types[j]+",";
-        }
-        requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
-        newAjaxRequest(requestString, "returnStep.php", function(result) {
-            content.innerHTML = result.responseText;
-            updateDividers();
-            sequencer.state.loaded = true;
-            for (var i = 0; i < sequencer.session.pipeline.upToDate.length; i++) {
-                sequencer.session.pipeline.upToDate.length[i] = true;
-            }
-            if (content.childNodes[0].nodeType == 3) content.removeChild(content.childNodes[0]);
+            args.push({
+                uid: sequencer.session.pipeline.uids[i],
+                type: sequencer.session.pipeline.types[i]
+            });
+            needsUpdating.push(new Array(i, sequencer.session.pipeline.uids[i], sequencer.session.pipeline.types[i]));
+        }
+        
+        requestString = "args="+JSON.stringify(args);
+        newAjaxRequest(requestString, "returnObjectDisplay.php", function(result){
+            content.removeChild(loadingGif);
+            insertNewObjects(result.responseText, needsUpdating);
         }, true);
+        sequencer.state.loaded = true;
+        var loadingGif = document.createElement("div");
+        loadingGif.innerHTML = "<img src='images/ui/ajax-loader-round.gif' style='float: left; margin:auto auto;' />";
+        content.appendChild(loadingGif);
     }
     else {
-        // Pack together all needed updates in one request string, insert responseText.firstChild whenever sequencer.session.pipeline.upToDate[i] == false
-        debugger;
-        var needsUpdating = new Array();
+        // This means that one or more steps are being added, not an entire pipeline's worth of them
+        needsUpdating = new Array();
+        args = [];
         // Add steps that need updating to the needsUpdating array (index, uid, type).
         for (var i = 0; i < sequencer.session.pipeline.uids.length; i++) {
             if (sequencer.session.pipeline.upToDate[i] == true) continue;
             needsUpdating.push(new Array(i, sequencer.session.pipeline.uids[i], sequencer.session.pipeline.types[i]));
-        }
-        // Now that we have an array of the steps that need to be refreshed, we compose a requestString.
-        var requestString = "uids=";
+            args.push({
+                uid: sequencer.session.pipeline.uids[i],
+                type: sequencer.session.pipeline.types[i]
+            });        
+        }
+        
+        requestString = "args="+JSON.stringify(args);
+        newAjaxRequest(requestString, "returnObjectDisplay.php", function(result){
+            insertNewObjects(result.responseText, needsUpdating);
+        }, true);
+        
+        // Optional bit with the loading GIF
         for (var i = 0; i < needsUpdating.length; i++) {
-            requestString += needsUpdating[i][1]+",";
-        }
-        if (requestString.slice(-1) == ",") requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
-        requestString += "&types=";
-        for (var i = 0; i < needsUpdating.length; i++) {
-            requestString += needsUpdating[i][2];
-        }
-        if (requestString.slice(-1) == ",") requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
-        
-        // perform the AJAX request
-        newAjaxRequest(requestString, "returnStep.php", function(result) {
-            insertNewSteps(result.responseText, needsUpdating);
-        }, true);
-    }
-    
+            var loadingDiv = document.createElement("div");
+            loadingDiv.className = "displayStep loading";
+            loadingDiv.innerHTML = "<img src='images/ui/ajax-loader-round.gif' />";
+            if (needsUpdating[i][0] > sequencer.state.numSteps-1) {
+                content.appendChild(loadingDiv);
+                sequencer.state.numSteps++;
+            }
+            else {
+                content.replaceChild(loadingDiv, content.childNodes[i][0]*2);
+            }
+        }
+        updateDividers();
+    // End optional
+    }
+    console.log(sequencer);
 }
 
 function loadSequencer() {
     /* 
-     * Description:
-     * Load data from hidden fields (put there by PHP), store them in the global var "sequencer" (as well as several initialization properties),
-     * then remove the hidden fields from the HTML document tree.
-     */
+ * Description:
+ * Load data from hidden fields (put there by PHP), store them in the global var "sequencer" (as well as several initialization properties),
+ * then remove the hidden fields from the HTML document tree.
+ */
     
     // Load hidden fields and set required properties in global object var.
     try {
-        
+        // settings fields first
+        initEditor();
+        
+        // Content-related fields next
         var fPipelineString = document.getElementById("pipelineStringField");
         var fPipelineTypes = document.getElementById("pipelineTypeField");
@@ -239,5 +260,4 @@
     hiddenInputs.parentNode.removeChild(hiddenInputs);
     
-    console.log(sequencer);
     // finally, run updateSequencer to refresh the visual display of the pipeline
     
@@ -245,62 +265,57 @@
 }
 
-function insertNewSteps(responseText, needsUpdating) {
-    debugger;
+function insertNewObjects(responseText, needsUpdating) {
+    var response = JSON.parse(responseText);
+    // For now I assume that only one type of element can be displayed in the editor at one time. Therefore, the type of response[0] is the type of all elements of response.
+    switch (response[0].type.toLowerCase()) {
+        case "survey": case "application": case "dashboard":
+            insertNewSteps(response, needsUpdating);
+            break;
+        case "question":
+            insertNewQuestions(response, needsUpdating);
+            break;
+        default:
+            break;
+                
+    }
+}
+
+function insertNewSteps(response, needsUpdating) {
+    /*
+ * This is a test function displaying how to handle the visual object representation in solely javascript.
+ * Communication of relevant variables between PHP and JS happens in JSON format.
+ * PHP returns a JSON array of objects to be created by JS
+ * JS then loops through this array and creates DIVS to be inserted into the sequencer.
+ * These are inserted at the position needsUpdating gives us.
+ */
     var content = document.getElementById("seqContentWrapper");
-    // Create a holder Div that converts the returned HTML to HTMLDivElements implicitly, so that they can be manipulated using DOM methods
-    var holderDiv = document.createElement("div");
-    holderDiv.innerHTML = responseText;
-    // tempDiv will serve to 
-    var tempDiv;
-    if (holderDiv.firstChild.nodeType == "3") holderDiv.removeChild(holderDiv.firstChild);
-    // Loop through 
-    for (var i = 0; i < needsUpdating.length; i++) {
-        tempDiv = holderDiv.firstChild;
-        holderDiv.removeChild(holderDiv.firstChild);
-        if (needsUpdating[i][0] > sequencer.state.numSteps-1) {
-            // this step comes at the end of the pipeline
-            content.appendChild(tempDiv);
-            sequencer.state.numSteps++;
-        }
-        else {
-            content.replaceChild(tempDiv, content.childNodes[needsUpdating[i][0]*2]);
-        }
-        // The element is now updated, therefore set this flag in the global var
-        sequencer.session.pipeline.upToDate[needsUpdating[i][0]] = true;
-    }
-    
-    // Then add or adjust dividers as needed!
-    updateDividers();
-}
-
-function insertNewQuestion(responseText, needsUpdating) {
-    /*
-     * This is a test function displaying how to handle the visual object representation in solely javascript.
-     * Communication of relevant variables between PHP and JS happens in JSON format.
-     * PHP returns a JSON array of objects to be created by JS
-     * JS then loops through this array and creates DIVS to be inserted into the sequencer.
-     * These are inserted at the position needsUpdating gives us.
-     */
-    
-    var content = document.getElementById("seqContent");
-    var response = eval(responseText);
+    // Remove optional loading images
+    for (var  i = 0; i < content.childNodes.length; i++) {
+        if (hasClass(content.childNodes[i], "loading")) {
+            content.removeChild(content.childNodes[i]);
+        }
+    }
+    // End optional
     
     for (var i = 0; i < response.length; i++) {
         var tempDiv = document.createElement("div");
-        tempDiv.id = response.id;
+        tempDiv.id = response[i].uid;
         tempDiv.className = "displayStep";
+        var divImageContainer = document.createElement("div");
+        divImageContainer.className = "displayStepIcon";
+        divImageContainer.addEventListener("click", function(){
+            clickStep(this.parentNode.id); 
+        }, false);
         var divImage = document.createElement("img");
-        divImage.src = "./images/displayStep.png";
-        divImage.addEventListener("Click", function(e){
-            selectStep(this.id);
-        }, false);
-        tempDiv.appendChild(divImage);
+        divImage.src = "images/icons/"+response[i].type.toLowerCase()+".png";
+        divImageContainer.appendChild(divImage);
+        tempDiv.appendChild(divImageContainer);
         var divLabel = document.createElement("p");
-        divLabel.innerHTML = response.title;
+        divLabel.innerHTML = response[i].title;
         tempDiv.appendChild(divLabel);
         
         // This for needs to loop backwards so that the steps at the end of the pipeline are added or changed first. This keeps the childNodes index for all further steps intact.
-        for (var j = needsUpdating.length; j >= 0; j--) {
-            if (needsUpdating[j][1] != response.id) continue;
+        for (var j = needsUpdating.length-1; j >= 0; j--) {
+            if (needsUpdating[j][1] != response[i].uid) continue;
             if (needsUpdating[j][0] > sequencer.state.numSteps-1) {
                 content.appendChild(tempDiv);
@@ -309,5 +324,64 @@
                 content.replaceChild(tempDiv, content.childNodes[j][0]*2);
             }
-        }
+            sequencer.session.pipeline.upToDate[needsUpdating[j][0]] = true;
+        }
+    }
+    
+    updateDividers();
+}
+
+function insertNewQuestions(response, needsUpdating) {
+    var content = document.getElementById("seqcContentWrapper");
+    // Loop through returned question objects
+    for (var i = 0; i < response.length; i++) {
+        // Define the outer frame
+        var frameDiv = document.createElement("div");
+        frameDiv.classname = "smallFrame question";
+        frameDiv.id = response[i].uid;
+        var titleDiv = document.createElement("div");
+        titleDiv.className = "smallTitle";
+        var numberDiv = document.createElement("div");
+        numberDiv.className = "listNumber";
+        numberDiv.innerHTML = i.toString();
+        titleDiv.appendChild(numberDiv);
+        titleDiv.innerHTML += response[i].uid;
+        frameDiv.appendChild(titleDiv);
+        
+        // The frame now has a header bar
+        // On to the content frame
+        // Will use new "ce();" function, shorthand for document.createElement
+        
+        var contentDiv = ce("div");
+        contentDiv.className = "content";
+        var questionBody = ce("p");
+        questionBody.innerHTML = response[i].description;
+        var questionParamsDiv = ce("div");
+        questionParamsDiv.className = "questionParamsView";
+        questionParamsDiv.innerHTML = "Object type: "+response[i].type;
+        contentDiv.appendChild(questionBody);
+        contentDiv.appendChild(questionParamsDiv);
+        frameDiv.appendChild(contentDiv);
+        
+        // And finally the controls div
+        var controlsDiv = ce("div");
+        controlsDiv.className = "controls";
+        var editButton = ce("input");
+        var removeButton = ce("input");
+        editButton.value = "Edit";
+        removeButton.value = "Remove";
+        editButton.className = "smallButton";
+        removeButton.className = "smallButton";
+        editButton.addEventListener("click", function(e){
+            alert('Editing not yet supported!');
+        }, false);
+        removeButton.addEventListener("click", function(e){
+            alert('Removing not yet supported!');
+        }, false);
+        controlsDiv.appendChild(editButton);
+        controlsDiv.appendChild(removeButton);
+        frameDiv.appendChild(controlsDiv);
+        
+    // We now have a full question display DIV contained in the frameDiv variable. We should now add this to the sequencer content.
+        
     }
 }
@@ -344,4 +418,5 @@
 
 function savePipeline (confirmSave) {
+    debugger;
     var answer;
     if (confirmSave == true) {
@@ -355,9 +430,12 @@
     var requestString = "uids=";
     requestString += arrayToString(sequencer.session.pipeline.uids, ",");
+    requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
     requestString += "&types=";
     requestString += arrayToString(sequencer.session.pipeline.types, ",");
+    requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
     requestString += "&sessionUid=";
     requestString += sequencer.session.uid;
-    newAjaxRequest(requestString, "savePipeline.php", function(result){
+    console.log(requestString);
+    newAjaxRequest(requestString, "savesession.php", function(result){
         console.log(result.responseText);
     }, true);
@@ -416,2 +494,32 @@
      
 }
+
+function initEditor() {
+    // load settings fields first
+    var fContentType = document.getElementById("sContentTypeField");
+    var content = document.getElementById("seqContent");
+    //sequencer.settings.content.contentType = fContentType.value.toLowerCase();
+    sequencer.settings.content.contentType = "survey";
+    
+    var desiredWidth, desiredHeight;
+    
+    //Then select settings from a few presets
+    switch (sequencer.settings.content.contentType) {
+        case "session":
+            sequencer.settings.content.orientation = "h";
+            sequencer.settings.content.width = 800;
+            sequencer.settings.content.height = 125;
+            content.style.width = sequencer.settings.content.width+"px";
+            content.style.height = sequencer.settings.content.height+"px";
+            break;
+        case "survey":
+            sequencer.settings.content.orientation = "v";
+            sequencer.settings.content.width = 600;
+            sequencer.settings.content.height = "auto";
+            content.style.width = sequencer.settings.content.width+"px";
+            content.style.height = sequencer.settings.content.height+"px";
+            break;
+        default:
+            break;
+    }
+}
