Index: /Dev/trunk/classes/pipelineSequencer.php
===================================================================
--- /Dev/trunk/classes/pipelineSequencer.php	(revision 180)
+++ /Dev/trunk/classes/pipelineSequencer.php	(revision 181)
@@ -60,42 +60,15 @@
             
             <div id="hiddenInputs">
-                <input type="hidden" name="selectedStep" id="selectedStepField" value="" />
-                <input type="hidden" name="pipelineString" id="pipelineStringField" value="<?php echo $stringPipeline; ?>" />
-                <input type="hidden" name="pipelineTypes" id="pipelineTypeField" value="<?php echo $stringPipelineType; ?>" />
-                <input type="hidden" name="pipelineUpDated" id="pipelineUpdatedField" value="<?php echo $stringPipelineUpdated; ?>" />
-                <input type="hidden" name="numSteps" id="numSteps" value="<?php echo $numberOfSteps; ?>" />
-                <input type="hidden" name="session" id="sessionField" value="<?php echo $this->loadedSession->uid; ?>" />
+                <input type="hidden" id="selectedStepField" value="" />
+                <input type="hidden" id="pipelineStringField" value="<?php echo $stringPipeline; ?>" />
+                <input type="hidden" id="pipelineTypeField" value="<?php echo $stringPipelineType; ?>" />
+                <input type="hidden" id="pipelineUpdatedField" value="<?php echo $stringPipelineUpdated; ?>" />
+                <input type="hidden" id="numSteps" value="<?php echo $numberOfSteps; ?>" />
+                <input type="hidden" id="sessionField" value="<?php echo $this->loadedSession->uid; ?>" />
+                <input type="hidden" id="sessionTitleField" value="<?php echo $this->loadedSession->title; ?>" />
             </div>
         </div>
 
-        <!--
-        <form name="sequencerForm" action="pipelineEditor.php" method="post">
-            <fieldset id="sequencer">
-                <div class="fieldsetTitle">Name: <?php echo $this->loadedSession->title; ?> </div>
-
-                <div id="seqContent">
-                    <div id="seqContentWrapper"></div>
-                </div>
-
-                <div id="controls">
-                    <input type="button" id="moveSelectedL" value="< Move" class="surveyButton"  onClick="moveStep(-1);" />
-                    <input type="button" id="moveSelectedR" value="Move >" class="surveyButton"  onClick="moveStep(1);" />
-                    <input type="button" id="editSelected" value="Edit step" class="surveyButton" onClick="editStep();" />
-                    <input type="button" id="deleteSelected" value="Delete step" class="surveyButton" onClick="deleteStep();" />
-                    <input type="submit" id ="clearPipeline" name="clearPipeline" value="Clear pipeline" class="surveyButton dis" disabled="true"/>
-                    <input type="checkbox" id="confirmClear" name="confirmClear" onChange="IsCheckEnabled(this, document.getElementById('clearPipeline'));" />Really clear?
-                    <input type="button" value="debug_save" onClick="savePipeline(true);" />
-                </div>
-                <div id="hiddenInputs">
-                    <input type="hidden" name="selectedStep" id="selectedStepField" value="" />
-                    <input type="hidden" name="pipelineString" id="pipelineStringField" value="<?php echo $stringPipeline; ?>" />
-                    <input type="hidden" name="pipelineTypes" id="pipelineTypeField" value="<?php echo $stringPipelineType; ?>" />
-                    <input type="hidden" name="pipelineUpDated" id="pipelineUpdatedField" value="<?php echo $stringPipelineUpdated; ?>" />
-                    <input type="hidden" name="numSteps" id="numSteps" value="<?php echo $numberOfSteps; ?>" />
-                    <input type="hidden" name="session" id="sessionField" value="<?php echo $this->loadedSession->uid; ?>" />
-                </div>
-            </fieldset>
-        </form>
-        -->
+        
         <?php
     }
@@ -103,9 +76,10 @@
     public function Javascript() {
         ?>
+        <script type="text/javascript" src="js/generalScripts.js"></script>
         <script type="text/javascript" src="js/sequencerScripts.js"></script>
         <script type="text/javascript" src="js/jquery.js"></script>
         <script type="text/javascript">
             $(document).ready(function() {
-                updateSequencer(true);      // true means it is the first refresh of the page.
+                loadSequencer();      // true means it is the first refresh of the page.
             });
         </script>
@@ -172,21 +146,4 @@
     }
 
-    // Dit is een pure php versie. Deze slaat nog niet op in de Database, en reageert nog niet op 
-    public function MoveStep($uid, $direction) {
-        $newSession = $this->loadedSession;
-
-        for ($i = 0; $i < count($newSession->pipeline); $i++) {
-            if ($newSession->pipeline[$i]->uid == $uid) {
-                $temp = $newSession->pipeline[$i];
-                $newSession->pipeline[$i] = $newSession->pipeline[$i + $direction];
-                $newSession->pipeline[$i + $direction] = $temp;
-                break;
-            }
-        }
-
-        $this->loadedSession = $newSession;
-        redirect("pipelineEditor.php");
-    }
-
 }
 ?>
Index: /Dev/trunk/css/visualeditors.css
===================================================================
--- /Dev/trunk/css/visualeditors.css	(revision 180)
+++ /Dev/trunk/css/visualeditors.css	(revision 181)
@@ -34,5 +34,4 @@
     padding: 2em 0;
 }
-
 
 .largeFrame {
@@ -128,14 +127,4 @@
 }
 
-
-
-
-
-
-
-
-
-
-
 .largeTitle {
     width: auto;
@@ -183,6 +172,4 @@
     font-weight: bold;
 }
-
-
 
 .bigButton {
@@ -207,5 +194,4 @@
     clear:both;
 }
-
 
 .smallButton {
@@ -231,7 +217,4 @@
 }
 
-
-
-
 /****************************/
 /* PIPELINE EDITOR SPECIFIC */
@@ -339,5 +322,4 @@
 /**************************/
 
-
 #surveyEditor {
     background-color: #0000FF;
Index: /Dev/trunk/js/generalScripts.js
===================================================================
--- /Dev/trunk/js/generalScripts.js	(revision 181)
+++ /Dev/trunk/js/generalScripts.js	(revision 181)
@@ -0,0 +1,134 @@
+/* 
+ * General functions, shared by most different scripts and elements.
+ */
+
+// Object literal version of a timer script, can be used to benchmark script running time.
+
+var timeDiff  =  {
+    setStartTime:function (){
+        d = new Date();
+        time  = d.getTime();
+    },
+
+    getDiff:function (){
+        d = new Date();
+        return (d.getTime()-time);
+    }
+}
+
+// Check if a certain HTMLElement has a given classname
+function hasClass(ele,cls) {
+    if (ele.className)
+        return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
+    
+}
+
+// Add a given classname to an HTMLElement
+function addClass(ele,cls) {
+    if (!this.hasClass(ele,cls)) ele.className += " "+cls;
+}
+
+// Remove a given class from an HTMLElement
+function removeClass(ele,cls) {
+    if (hasClass(ele,cls)) {
+        var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
+        ele.className=ele.className.replace(reg,' ');
+    }
+}
+
+// General function to handle AJAX functionality.
+// Specify the request string, url to send to, the function to execute on response and whether to run in the background or wait for a response before continuing.
+function newAjaxRequest(c, u, cb, async) {
+    var xml;
+    var content = c;    //an array of strings, in "key=value"  format.
+    // assign a compatible request format
+    if (window.XMLHttpRequest) {    //Not IE5, IE6
+        xml = new XMLHttpRequest();
+    }
+    else {                          //IE5, IE6
+        xml = new ActiveXObject("Microsoft.XMLHTTP");
+    }
+    // subscribe the callback function to a response event
+    xml.onreadystatechange = function() {
+        xml.responseText = "Processing...";
+        if (xml.readyState == 4 && xml.status == 200) {
+            cb(xml);
+        }
+    };
+    // initialize XMLRequest
+    xml.open("POST", u, async);
+    xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+    var contentString = "";
+    //iterate through parameters passed in variable c
+    if (typeof(content)=='object'&&(input instanceof Array)) {    // parameters were passed as an array of key=value strings
+        for (var i = 0; i < content.length; i++) {
+            contentString += content[i];
+            if (i != (content.length - 1)) {
+                contentString += "&";
+            }
+        }
+    }
+    else { // single parameter or string already formatted by calling function
+        contentString = content;
+    }
+    // finally send the formatted request
+    xml.send(contentString);
+}
+
+// Function to save the object currently being edited.
+// !! Still needs to be generalized !!
+function saveObject (confirmSave) {
+    var answer = false;
+    if (confirmSave==true) {
+        answer = confirm("Save changes to pipeline?");
+    }
+    else {
+        answer = true;
+    }
+    
+    
+    if (answer == true) {
+        var pipeline = document.getElementById("pipelineStringField").value;
+        pipeline = pipeline.slice(0, pipeline.length - 1);
+        var types = document.getElementById("pipelineTypeField").value;
+        types = types.slice(0, types.length - 1);
+        var session = document.getElementById("sessionField").value;
+        var requestString = "uids="+pipeline+"&types="+types+"&sessionUid="+session;
+        console.log(requestString);
+        
+        
+        var success;
+        newAjaxRequest(requestString, "savesession.php", function(result){
+            success = result.responseText;
+        }, true);
+        console.log(success);
+    }
+}
+
+// Convert a string to an array and remove any empty items (from trailing commas)
+function stringToArray(s, c) {
+    var a = s.split(c);
+    for (var i = 0; i < a.length; i++) {    // remove empty items
+        if (a[i] == "") {
+            a.splice(i, 1);
+            i--;
+        }
+    }
+    return a;
+}
+
+// Convert an array to a string, separated by character "c"
+function arrayToString(a, c) {
+    var s = "";
+    for (var i = 0; i < a.length; i++) {
+        if (a[i] != "") {
+            s += a[i]+c;
+        }
+    }
+    return s;
+}
+
+// Remove all newlines, carriage returns and tabs from a given string
+function removeNL(s){ 
+    return s.replace(/[\n\r\t]/g,""); 
+}
Index: /Dev/trunk/js/sequencerScripts.js
===================================================================
--- /Dev/trunk/js/sequencerScripts.js	(revision 180)
+++ /Dev/trunk/js/sequencerScripts.js	(revision 181)
@@ -3,241 +3,124 @@
  * and open the template in the editor.
  */
-var timeDiff  =  {
-    setStartTime:function (){
-        d = new Date();
-        time  = d.getTime();
+
+var sequencer = {   // GLOBAL VAR TO STORE SEQUENCER SETTINGS!
+    uid: "",                // The unique id of this sequencer (not DB related!). This will help to avoid global var conflicts. Assign this randomly! (STRING)
+    session: {              // Properties of the currently loaded session
+        title: "",              // Title or name (STRING)
+        uid: "",                // Database UID of the current session (STRING)
+        pipeline: {             // Pipeline
+            uids: [],               // Uids of objects in pipeline (STRING)
+            types: [],              // Types of objects in pipeline (STRING)
+            upToDate: []            // Whether or not object displays are up to date (BOOL)
+        }
     },
-
-    getDiff:function (){
-        d = new Date();
-        return (d.getTime()-time);
-    }
-}
-
-
-
-
-
-function IsItemSelected(check, target) {
-    if (check.value) {
-        target.disabled = false;
-    }
-    else {
-        target.disabled = true;
-    }
-}
-
-function IsCheckEnabled(check, target) {
-    if (check.checked) {
-        target.disabled = false;
-        this.removeClass(target, "dis");
-        
-    }
-    else {
-        target.disabled = true;
-        this.addClass(target, "dis");
-    }
-}
-
-function removeNL(s){ 
-    return s.replace(/[\n\r\t]/g,""); 
-}
+    state: {                // Operating state of the sequencer
+        numSteps: 0,            // Number of steps currently drawn in the editor (not necessarily same as number of steps in pipeline!) (INTEGER)
+        loaded: false,          // Whether or not the sequencer content has been updated for the first time (BOOL)
+        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)
+        }        
+    },
+    settings: {             // Various settings to determine the workings of the sequencer
+        content: {              // Properties related to the content view of the sequencer
+            width: null,            // Width of the viewing area (INTEGER)
+            height: null,           // Height of the viewing area (INTEGER)
+            maxObjects: null,       // The maximum number of content elements to be displayed at once time (INTEGER)
+            orientation: "horizontal"        // Whether the editor should be a vertical or horizontal editor (STRING)
+        },
+        efficientUpdating: true // Whether or not to use selective querying of the database for new step objects. True will only refresh out-of-date steps, False will refresh the whole pipeline
+    }
+}
+
 
 function SubmitToolbox(type) {
+    deselectStep();
     var c = "objectToCreate="+type;
     var u = "createObject.php";
-    var a = true;
-    var pipeline = document.getElementById("pipelineStringField");
-    var pipelineType = document.getElementById("pipelineTypeField");
-    var pipelineUpdated = document.getElementById("pipelineUpdatedField");
-    document.getElementById("numSteps").value++;
-    
-    newAjaxRequest(c, u, function(result){
-        var resultUid = removeNL(result.responseText);
-        //resultUid.replace("\n","").replace("\r","");
-        
-        pipeline.value += resultUid+",";
-        pipelineType.value += type+",";
-        pipelineUpdated.value += "0,";
+        
+    newAjaxRequest(c, u, function(result) {
+        sequencer.session.pipeline.uids.push(removeNL(result.responseText));
+        sequencer.session.pipeline.types.push(type);
+        sequencer.session.pipeline.upToDate.push(false);
         updateSequencer();
-    }, a);
-}
-
-// Class manipulation
-
-function hasClass(ele,cls) {
-    if (ele.className)
-        return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
-}
- 
-function addClass(ele,cls) {
-    if (!this.hasClass(ele,cls)) ele.className += " "+cls;
-}
- 
-function removeClass(ele,cls) {
-    if (hasClass(ele,cls)) {
-        var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
-        ele.className=ele.className.replace(reg,' ');
-    }
-}
-
-//new scripts!
-//start here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    }, true);
+}
+
+function clickStep(uid) {
+    if (uid == sequencer.state.selectedStep.uid) {  // user deselected a currently selected step.
+        deselectStep();
+    }
+    else {
+        if (sequencer.state.selectedStep.uid != undefined && sequencer.state.selectedStep.uid != "") {
+            deselectStep();
+            selectStep(uid);
+        }
+        else {
+            selectStep(uid);
+        }        
+    }
+}
 
 function selectStep(uid) {
-    /*
-    
-    var nodes = document.getElementById("seqContentWrapper").childNodes;
-    for (var i = 0; i < nodes.length; i++) {     //loop through childNodes. Skip first node (whitespace)
-        if (hasClass(nodes[i], "displayStep")) {    //check if current childNode is a displayStep, not divider or text.
-            if (nodes[i].id == uid) {
-                if (hasClass(nodes[i], "selected")) {
-                    removeClass(nodes[i], "selected");
-                }
-                else {
-                    addClass(nodes[i], "selected");
-                }                
-            }
-            else {
-                removeClass(nodes[i], "selected");
-            }
-        }
-    }
-    */
-    // Hier is een snellere manier voor!
     var element = document.getElementById(uid);
-    var prevElement = document.getElementById(document.getElementById("selectedStepField").value);
-    
-    if (!element || !hasClass(element, "displayStep")) {
+    if (element) {
+        addClass(element, "selected");
+        var type = sequencer.session.pipeline.types[sequencer.session.pipeline.uids.indexOf(uid)];
+        ajaxInfoRequest(uid, document.getElementById("infoPanelContent"), type);
+        sequencer.state.selectedStep.uid = uid;
+        sequencer.state.selectedStep.index = null;  //Don't know how to do this yet.
+    }
+}
+
+function deleteStep() {
+    // check if a step is selected
+    if (sequencer.state.selectedStep.uid == null) {
         return;
     }
-    // misschien nog checks inbouwen of het echt wel een element is?
-    var selectedStepField = document.getElementById("selectedStepField");
-    if (!hasClass(element, "selected")) {
-        if (prevElement) {
-            removeClass(prevElement, "selected");
-        }
-        addClass(element, "selected");
-        selectedStepField.value = uid;
-        
-        var pl = stringToArray(document.getElementById("pipelineStringField").value, ",");
-        var plType = stringToArray(document.getElementById("pipelineTypeField").value, ",");
-        var type = plType[pl.indexOf(uid)];
-        ajaxInfoRequest(uid, document.getElementById("infoPanelContent"), type);
-        
-        
-    }
-    else {
-        deselectStep(uid);
-    }
-    
-    
-// Update selected step field with uid of currently selected step.
-    
-    
-}
-
-function deleteStep() {
-    // delete an object from the session.
-    // note: does not actually remove the object from the database, only takes it out of the pipeline array.
-        
-    var pl = stringToArray(document.getElementById("pipelineStringField").value, ",");
-    var plType = stringToArray(document.getElementById("pipelineTypeField").value, ",");
-    var plUpdated = stringToArray(document.getElementById("pipelineUpdatedField").value, ",");
-    var selectedStep = document.getElementById("selectedStepField").value;
-    
-    // if no step has been selected, exit the function
-    if (selectedStep == undefined || selectedStep == "") {
-        return;
-    }
-    
-    // find the array index of the specified object uid, then remove it from all three arrays.
-    var index = pl.indexOf(selectedStep);
-    if (index >= 0 && index < pl.length) {
-        pl.splice(index, 1);
-        plType.splice(index, 1);
-        plUpdated.splice(index, 1);
-        // set the updated status of all objects from *index* and forward to "0" (out of date)
-        // this way they will be refreshed the next time updateSequencer(); is called, adn the visual display will match the new pipeline.
-        for (var i = index-1; i < plUpdated.length; i++) {
-            if (i >= 0 ) {
-                plUpdated[i] = "0";
-            }
-        }
-    }
-    
-    document.getElementById("pipelineStringField").value = arrayToString(pl, ",");
-    document.getElementById("pipelineTypeField").value = arrayToString(plType, ",");
-    document.getElementById("pipelineUpdatedField").value = arrayToString(plUpdated, ",");
-    deselectStep(selectedStep);     // Make sure the info panel is up to date as well. (Not showing anything, as it should be...)
-    document.getElementById("numSteps").value--;
-    
-    updateSequencer(false);
-    
-    
-    
-}
-
-function deselectStep(uid) {
-    var field = document.getElementById("selectedStepField");
-    field.value = "";
-    var element = document.getElementById(uid);
+    var uid = sequencer.state.selectedStep.uid;
+    // deselect the step to reset the info panel and selection code
+    deselectStep();
+    // splice the step's data from the pipeline
+    var index = sequencer.session.pipeline.uids.indexOf(uid);
+    if (index >= 0 && index < sequencer.session.pipeline.uids.length) {
+        sequencer.session.pipeline.uids.splice(index, 1);
+        sequencer.session.pipeline.types.splice(index, 1);
+        sequencer.session.pipeline.upToDate.splice(index, 1);
+        // Then delete the step visually
+        var element = document.getElementById(uid);
+        var divider;
+        if (!element.nextSibling) {
+            // the element is at the end of the pipeline
+            // therefore we remove the previous divider.
+            // Note: it could also be the only element left in the pipeline!
+            divider = (element.previousSibling) ? element.previousSibling : false;
+            if (divider != false) {
+                divider.parentNode.removeChild(divider);
+            }
+        }
+        else {
+            // the element is at any position except the last, therefore we remove the next divider
+            divider = (element.nextSibling) ? element.nextSibling : false;
+            if (divider != false) {
+                divider.parentNode.removeChild(divider);
+            }
+        }
+        
+        // Finally, remove the element itself.
+        element.parentNode.removeChild(element);
+        sequencer.state.numSteps--;
+        
+    }
+}
+
+function deselectStep() {
+    if (!sequencer.state.selectedStep.uid) return;
+    var element = document.getElementById(sequencer.state.selectedStep.uid);
     removeClass(element, "selected");
-    document.getElementById("infoPanelContent").innerHTML = "";
-}
-                                                                            
-function newAjaxRequest(c, u, cb, async) {
-    
-    var xml;
-    var content = c;    //an array of strings, in "key=value"  format.
-    // assign a compatible request format
-    if (window.XMLHttpRequest) {    //Not IE5, IE6
-        xml = new XMLHttpRequest();
-    }
-    else {                          //IE5, IE6
-        xml = new ActiveXObject("Microsoft.XMLHTTP");
-    }
-    // subscribe the callback function to a response event
-    xml.onreadystatechange = function() {
-        xml.responseText = "Processing...";
-        if (xml.readyState == 4 && xml.status == 200) {
-            cb(xml);
-        }
-    };
-    // initialize XMLRequest
-    xml.open("POST", u, async);
-    xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
-    var contentString = "";
-    //iterate through parameters passed in variable c
-    if (typeof(content)=='object'&&(input instanceof Array)) {    // parameters were passed as an array of key=value strings
-        for (var i = 0; i < content.length; i++) {
-            contentString += content[i];
-            if (i != (content.length - 1)) {
-                contentString += "&";
-            }
-        }
-    }
-    else { // single parameter or string already formatted by calling function
-        contentString = content;
-    }
-    // finally send the formatted request
-    xml.send(contentString);
-}
-
-
-/*
- * ajaxStepRequest gets  the markup for displaying a step in the sequencer from returnStep.php
- * Using ajax principle allows for editing of pipeline without constantly refreshing the page.
- */
-
-function ajaxStepRequest(UIDS, types) {
-    var c = "uids="+UIDS;
-    if (types != "") {
-        c += "&types="+types;
-    }
-    var u = "returnStep.php";
-    newAjaxRequest(c, u, function(result) {
-        document.getElementById("seqContentWrapper").innerHTML = result.responseText;
-    }, true);
+    sequencer.state.selectedStep.uid = null;
+    sequencer.state.selectedStep.index = null;
+    var infoPanel = document.getElementById("infoPanelContent");
+    while (infoPanel.firstChild) infoPanel.removeChild(infoPanel.firstChild);
 }
 
@@ -251,190 +134,183 @@
 }
 
-function drawSteps2() {
+function updateSequencer() {
+
+    /*
+ * 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 pipeline = document.getElementById("pipelineStringField").value;
-    var pipelineTypes = document.getElementById("pipelineTypeField").value;
-    var numSteps = document.getElementById("numSteps").value;
-    if (numSteps > 0) {
-        pipeline = pipeline.replace(/,/g , ",divider,");    //regex search for commas, global (repeat), to represent them with visual dividers.
-        pipelineTypes = pipelineTypes.replace(/,/g, ",divider,");
-        ajaxStepRequest(pipeline, pipelineTypes);
-    }
-}
-
-
-function updateSequencer(firstLoad) {
-    // Load hidden field values
-    
-    var plString = document.getElementById("pipelineStringField").value;
-    var plTypeString = document.getElementById("pipelineTypeField").value;
-    var plUpdatedString = document.getElementById("pipelineUpdatedField").value;
-    var count = document.getElementById("numSteps").value;
-    
-    if (count < 1) {
-        document.getElementById("seqContentWrapper").innerHTML = "";
-        return;
-    }
-    // If this is on page-load time
-    if (firstLoad == true) {
-        var seqContent = document.getElementById("seqContentWrapper");
-        seqContent.innerHTML = "";
-        requestString = plString.slice(0, -1);
-        requestString = requestString.replace(/,/g, ",divider,");
-        newAjaxRequest("uids="+requestString, "returnStep.php", function(result) {
-            seqContent.innerHTML = result.responseText;
+    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
+        // 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=";
+        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;
+            }
         }, true);
-        
-        plUpdatedString = "";
-        for (var i = 0; i < plString.split(",").length-1; i++) {
-            plUpdatedString += "1,";
-        }
-        
-        document.getElementById("pipelineUpdatedField").value = plUpdatedString;
-    }
-    else {      // if not
-        var pl = stringToArray(plString, ",");    
-        var plType = stringToArray(plTypeString, ",");    
-        var plUpdated = stringToArray(plUpdatedString, ",");
-    
-        var count = pl.length;
-    
-        document.getElementById("numSteps").value = count;
-        var seqContent = document.getElementById("seqContentWrapper");
-        // hier zit een fout. Als er een deleted step nog in de pipeline staat haalt hij de eerste valid step weg ipv een text node.
-        // twee mogelijkheden: 
-        // 1: check of het text node is.
-        // 2: modulo check of het een even aantal steps is. Als alles klopt kan er onmogelijk een even aantal childNodes zijn.
-        if (seqContent.childNodes.length % 2 == 0 && seqContent.childNodes.length > 0) {
-            seqContent.removeChild(seqContent.childNodes[0]);
+    }
+    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();
+        
+        // DIT IS FOUT.
+        // BASIC IDEE, IK LOOP NU DOOR DE CHILNODES HEEN, EN NIET DOOR DE PIPELINE ARRAY. HIERDOOR KAN JE NOOIT EEN NIEUWE OBJECT DRAWEN, WANT DAAR IS IN DE SEQUENCER NOG GEEN DIV VOOR.
+        // OPLOSSING: 
+        // LOOP DOOR SEQUENCER EN HAAL ALLES WEG DAT ER NIET HOORT (CROSSCHECK DISPLAYSTEP UID MET ARRAY)
+        // LOOP DAARNA DOOR DE PIPELINE EDITOR, CHECK OF ER ELEMENTS VOOR ZIJN. ZO NIET, VOEG TOE AAN DE EDITOR!
+        
+        for (var i = 0; i < sequencer.session.pipeline.uids.length; i++) {
             
         }
         
-        
-        for (var i = 0; i < pl.length; i++) {   // loop through pipeline contents
-            if (plUpdated[i] == "0") {   // if the element is not up to date
-                // first remove the step representation from the sequencer
-                //timeDiff.setStartTime();
-                
+        for (var i = 0; i < content.childNodes.length; i++) {
+            // If this childNode is not a displayStep, continue to the next childNode
+            if (!hasClass(content.childNodes[i], "displayStep")) continue;
+            // If this step is up to date, continue
+            // pseudo: the upToDate entry on the index where childNodes[i].id is stored in uids
+            if (sequencer.session.pipeline.upToDate[sequencer.session.pipeline.uids.indexOf(content.childNodes[i].id)] == true) continue;
             
-                // IMPROVISE !!!!!!!!!!
-                var elementByIndex = seqContent.childNodes[2*i];    // works with moved steps
-                var elementById = document.getElementById(pl[i]);   // works with ???, not moved steps though... Keeping this in here for future bugfixing. This value is not currently used.
-                var element = elementByIndex;
-            
-            
-                // END IMPROVISE !!!!!!!!!!!!
-                if (element == null) {
-                    element = document.createElement("div");
-                    element.name = "placeholder";
-                    seqContent.appendChild(element);
-                }
-                if (element.nextSibling) {
-                    var nextElement = element.nextSibling;
-                }
-                else {
-                    var nextElement = document.createElement("div");
-                    nextElement.name = "placeholderNext";
-                    seqContent.appendChild(nextElement);
-                }
-            
-                // now request a new step representation and insert it after previousElement
-                var holderDiv = document.createElement("div");
-                var requestString = "uids="+pl[i];
-            
-                if (plType[i]) {
-                    requestString += "&types="+plType[i];
-                }
-                // globally declare newDiv so it can be passed to the updateDividers function
-                var newDiv;
-            
-                newAjaxRequest(requestString, "returnStep.php", function(result) {
-                    holderDiv.innerHTML = result.responseText;
-                    newDiv = holderDiv.childNodes[1];            
-                    seqContent.replaceChild(newDiv, element);
-                    if (nextElement.name == "placeholderNext") {
-                        seqContent.removeChild(nextElement);
-                    }
-                    plUpdated[i] = "1";
-                }, false);
-            
-                       
-                // ALTERNATIVE METHOD TO REPLACECHILD!!!
-                //seqContent.removeChild(element);
-                //seqContent.insertBefore(newDiv, nextElement);
-            
-                // Now check if dividers are necessary.
-            
-                //alert("INSERT CODE FOR UPDATEDIVIDERS HERE!");
-                //alert(timeDiff.getDiff());
-                
-                // If seqContent contains any further entries when the last pipeline uid has been drawn, these are to be removed.
-                // This happens after the user performs a "delete step" operation and there is now one fewer step in the array than in seqContent.
-                // All steps other than the first and the last are auto-adjusted due to "out of date" flag.
-                if (i >= pl.length - 1) {
-                    
-                    // This is a really complicated way of saying "Delete the next two elements if they exist"
-                    while ((nextElement = newDiv.nextSibling) != undefined) {
-                        seqContent.removeChild(nextElement);
-                    }
-                    
-                }
-                // Do the same check for the first step in the pipeline. 
-                // Is there no more elegant solution for this? For instance, check if a step should be in the pipeline in the first place, else delete it and it's following divider
-                
-                
-                updateDividers(newDiv);
-            }
-        }
-    
-        // afterwards, convert the arrays back to strings and set to appropriate fields
-        var newUpdatedString = arrayToString(plUpdated, ",");
-        document.getElementById("pipelineUpdatedField").value = newUpdatedString;
-    }
-}
-
-
-
-
-
-
-function updateDividers (element) {
-    var seqContent = document.getElementById("seqContentWrapper");
-    
-    if (element.nextSibling){
-        var nextElement = element.nextSibling;
-    }
-    if (element.previousSibling) {
-        var previousElement = element.previousSibling;
-    }
-    
-    if (nextElement){
-        if (!hasClass(nextElement, "divider")) {
-            var holderDiv = document.createElement("div");
-            newAjaxRequest("uids=divider&types=divider", "returnStep.php", function(result) {
-                holderDiv.innerHTML = result.responseText;
-                var newDivider = holderDiv.childNodes[1];
-                seqContent.insertBefore(newDivider, nextElement);
-            }, false);
-        }
-    }
-    
-    if (previousElement){
-        if (!hasClass(previousElement, "divider")) {
-            var holderDiv = document.createElement("div");
-            newAjaxRequest("uids=divider&types=divider", "returnStep.php", function(result) {
-                holderDiv.innerHTML = result.responseText;
-                var newDivider = holderDiv.childNodes[1];
-                seqContent.insertBefore(newDivider, element);
-            }, false);
-        }
-    }
-    
-}
-
-
-
-
-
+            // So now we know that we are looking at a displayStep and it needs to be refreshed.
+            // We store the current childNodes index, the uid of the proper displayStep and the type of the proper displayStep in needsUpdating array.
+            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.
+        requestString = "uids=";
+        for (var i = 0; i < needsUpdating.length; i++) {
+            requestString += needsUpdating[i][1]+",";   // comma separated, of course
+        }
+        requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
+        requestString += "&types=";
+        for (var i = 0; i< needsUpdating.length; i++) {
+            requestString += needsUpdating[i][2]+",";
+        }
+        requestString = requestString.slice(0, requestString.length - 1);   // remove trailing commas
+        
+        // Now it is time to send this string to returnStep.php (Soon to be returnStepDisplay.php!).
+        
+        alert(requestString);
+        newAjaxRequest(requestString, "returnStep.php", function(result) {
+            //alert(result.responseText);
+            insertNewSteps(responseText);
+        }, true);
+    }
+    
+}
+
+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.
+     */
+    
+    // Load hidden fields and set required properties in global object var.
+    try {
+        
+        var fPipelineString = document.getElementById("pipelineStringField");
+        var fPipelineTypes = document.getElementById("pipelineTypeField");
+        var fSessionUid = document.getElementById("sessionField");
+        var fSessionTitle = document.getElementById("sessionTitleField");
+    
+        sequencer.session.title = fSessionTitle.value;
+        sequencer.session.uid = fSessionUid.value;
+        sequencer.session.pipeline.uids = stringToArray(fPipelineString.value, ",");
+        sequencer.session.pipeline.types = stringToArray(fPipelineTypes.value, ",");
+        sequencer.session.pipeline.upToDate = new Array();
+        
+        for (var i = 0; i < sequencer.session.pipeline.uids.length; i++) {
+            sequencer.session.pipeline.upToDate.push(true);
+        }
+        sequencer.state.numSteps = 0;
+        sequencer.state.loaded = false;
+        sequencer.settings.content.orientation = "h";
+        sequencer.settings.efficientUpdating = true;
+    }
+    catch (e) {
+        // Alert developer of any errors while setting these variables
+        for (error in e) alert(error.message);
+    }
+    
+    // Then remove the hidden fields from the HTML document
+    var hiddenInputs = document.getElementById("hiddenInputs");
+    hiddenInputs.parentNode.removeChild(hiddenInputs);
+    
+    console.log(sequencer);
+    // finally, run updateSequencer to refresh the visual display of the pipeline
+    
+    updateSequencer();
+}
+
+function insertNewSteps(responseText) {
+    debugger;
+    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;
+    // Loop through 
+    for (var i = 0; i < content.childNodes.length; i++) {
+        // Once again, skip if not a displayStep or the given displayStep is already up to date.
+        if (!hasClass(content.childNodes[i], "displayStep")) continue;
+        if (sequencer.session.pipeline.upToDate[sequencer.session.pipeline.uids.indexOf(content.childNodes[i].id)] == true) continue;
+        tempDiv = holderDiv.firstChild;
+        holderDiv.removeChild(holderDiv.firstChild);
+        content.replaceChild(tempDiv, content.childNodes[i]);
+        // Exit the loop if there is no more responsetext
+        if (!holderDiv.firstChild) break;
+    }
+}
+
+function updateDividers() {
+    var content = document.getElementById("seqContentWrapper");
+    for (var i = 0; i < content.childNodes.length; i++) {
+        var element = content.childNodes[i];
+        if (!hasClass(element, "displayStep")) {
+            continue;
+        }
+        var lastElement = (element.previousSibling && element.previousSibling.nodeName == "DIV") ? element.previousSibling : false;
+        var nextElement = (element.nextSibling && element.nextSibling.nodeName == "DIV") ? element.nextSibling : false;
+        if (lastElement != false) {
+            if (!hasClass(lastElement, "divider")){
+                var newDivider = document.createElement("div");
+                addClass(newDivider, "divider");
+                addClass(newDivider, sequencer.settings.content.orientation);
+                content.insertBefore(newDivider, element);
+                delete newDivider;
+            }
+        }
+        if (nextElement != false) {
+            if (!hasClass(nextElement, "divider")){
+                var newDivider = document.createElement("div");
+                addClass(newDivider, "divider");
+                addClass(newDivider, sequencer.settings.content.orientation);
+                content.insertBefore(newDivider, nextElement);
+                delete newDivider;
+            }
+        }
+    }
+}
 
 function savePipeline (confirmSave) {
@@ -465,114 +341,54 @@
 }
 
-function t_setOutOfDate() {
-    // if a step is currently selected
-    var uid = document.getElementById("selectedStepField").value;
-    if (uid == "") {
-        alert("No step selected!");
-        return;
-    }
-    
-    // convert to arrays for looping
-    var plString = document.getElementById("pipelineStringField").value;
-    var plTypeString = document.getElementById("pipelineTypeField").value;
-    var plUpdatedString = document.getElementById("pipelineUpdatedField").value;
-    
-    
-    var pl = stringToArray(plString, ",");    
-    var plType = stringToArray(plTypeString, ",");    
-    var plUpdated = stringToArray(plUpdatedString, ",");    
-    
-    // set the targeted element's tag for "Needs updating"
-    plUpdated[pl.indexOf(uid)] = "0";
-    
-    // then rewrite the content strings and set them to the appropriate fields
-    var newUpdatedString = arrayToString(plUpdated, ",");
-    document.getElementById("pipelineUpdatedField").value = newUpdatedString;
-}
-
-function stringToArray(s, c) {
-    var a = s.split(c);
-    for (var i = 0; i < a.length; i++) {    // remove empty items
-        if (a[i] == "") {
-            a.splice(i, 1);
-            i--;
-        }
-    }
-    return a;
-}
-
-function arrayToString(a, c) {
-    var s = "";
-    for (var i = 0; i < a.length; i++) {
-        if (a[i] != "") {
-            s += a[i]+c;
-        }
-    }
-    return s;
-}
-
-
 function editStep() {
-    // eerst saven, dan de object type zoeken in de typelist, dan redirecten naar de goede pagina
-    savePipeline(false);
-    
-    var pipeline = document.getElementById("pipelineStringField").value;
-    var pipelineTypes = document.getElementById("pipelineTypeField").value;
-    var selectedStep = document.getElementById("selectedStepField").value;
-    pipeline = stringToArray(pipeline, ",");
-    pipelineTypes = stringToArray(pipelineTypes, ",");
-    var stepType = pipelineTypes[pipeline.indexOf(selectedStep)];
+    // first save
+    
+    //savePipeline(false);
+    
     var postForm = document.createElement("form");
-    postForm.action = stepType.toLowerCase()+"Editor.php";      //redirect to "type"editor.php
+    var type = sequencer.session.pipeline.types[sequencer.session.pipeline.uids.indexOf(sequencer.state.selectedStep.uid)];
+    postForm.action = type.toLowerCase()+"Editor.php";
     postForm.method = "POST";
     var objectUid = document.createElement("input");
     objectUid.type = "hidden";
     objectUid.name = "objectUid";
-    objectUid.value = selectedStep;
+    objectUid.value = sequencer.state.selectedStep.uid;
     postForm.appendChild(objectUid);
     postForm.submit();
 }
 
-
-
 function moveStep (direction) {
-    // misschien maar eens een loadhiddenfields functie maken voor deze meuk?
-    
-    var selectedStep = document.getElementById("selectedStepField").value;
-    
-    if (selectedStep != undefined && selectedStep != "") {
-        var pipeline = stringToArray(document.getElementById("pipelineStringField").value, ",");
-        var pipelineTypes = stringToArray(document.getElementById("pipelineTypeField").value, ",");
-        var updated = stringToArray(document.getElementById("pipelineUpdatedField").value, ",");
-    }
-    else {
-        alert("No step selected! Unable to move");
-        return;
-    }
-    
-    var id = pipeline.indexOf(selectedStep);
-    if ((id == 0 && direction == -1) || (id == pipeline.length-1 && direction == 1)){
+    // Check if a step is selected
+    
+    if (sequencer.state.selectedStep.uid == null || direction == null) return;
+    // Check if the step is not at either end of the pipeline
+    var index = sequencer.session.pipeline.uids.indexOf(sequencer.state.selectedStep.uid);
+    if ((index < 0) || (index >= sequencer.session.pipeline.uids.length) || (index == 0 && direction == -1) || (index == sequencer.session.pipeline.uids.length - 1 && direction == 1)) {
         alert("Cannot move out of bounds!");
         return;
     }
-    var tempString = pipeline[id], tempType = pipelineTypes[id];
-    
-    pipeline[id] = pipeline[id+direction];
-    pipelineTypes[id] = pipelineTypes[id+direction];
-    pipeline[id+direction] = tempString;
-    pipelineTypes[id+direction] = tempType;
-    updated[id] = "0";
-    updated[id+direction] = "0";
-    
-    pipeline = arrayToString(pipeline, ",");
-    pipelineTypes = arrayToString(pipelineTypes, ",");
-    updated = arrayToString(updated, ",");
-    
-    document.getElementById("pipelineStringField").value = pipeline;
-    document.getElementById("pipelineTypeField").value = pipelineTypes;
-    document.getElementById("pipelineUpdatedField").value = updated;
-    updateSequencer();
-    
-    // Then reselect the previously selected step
-    addClass(document.getElementById(selectedStep), "selected");
-}
+    
+    // Find the two elements in the editor content display
+    var content = document.getElementById("seqContentWrapper");
+    var element = document.getElementById(sequencer.session.pipeline.uids[index]);
+    var otherElement = document.getElementById(sequencer.session.pipeline.uids[index+direction]);
+    // First buffer the two elements
+    var tempElement = element.cloneNode(true);
+    var tempOtherElement = otherElement.cloneNode(true);
+    var placeHolderElement = document.createElement("div");
+    placeHolderElement.id = "placeholder_element";
+    content.replaceChild(placeHolderElement, otherElement);
+    content.replaceChild(tempOtherElement, element);
+    content.replaceChild(tempElement, placeHolderElement);
+    //This should work.
+    // A-B     Start positions, backup to tA and tB
+    // A-X     Replace B with placeholder X
+    // B-X     Replace A with tB
+    // B-A     Replace placeholder X with tA.
+    // The two elements are now swapped.
+     
+    // Now swap the array entries.
+    sequencer.session.pipeline.uids[index] = sequencer.session.pipeline.uids.splice(index+direction, 1, sequencer.session.pipeline.uids[index])[0];
+    sequencer.session.pipeline.types[index] = sequencer.session.pipeline.types.splice(index+direction, 1, sequencer.session.pipeline.types[index])[0];
+     
+}
Index: /Dev/trunk/js/sequencerScripts_1.js
===================================================================
--- /Dev/trunk/js/sequencerScripts_1.js	(revision 181)
+++ /Dev/trunk/js/sequencerScripts_1.js	(revision 181)
@@ -0,0 +1,561 @@
+//THIS IS THE BACKUP!!!!!!!
+
+/* 
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+var sequencer = {   // GLOBAL VAR TO STORE SEQUENCER SETTINGS!
+    uid: "",                // The unique id of this sequencer (not DB related!). This will help to avoid global var conflicts. Assign this randomly!
+    session: {              // Properties of the currently loaded session
+        title: "",              // Title or name
+        uid: "",                // Database UID of the current session
+        pipeline: {             // Pipeline
+            uids: [],               // Uids of objects in pipeline
+            types: [],              // Types of objects in pipeline
+            upToDate: []            // Whether or not object displays are up to date
+        }
+    },
+    state: {                // Operating state of the sequencer
+        numSteps: 0,            // Number of steps currently drawn in the editor (not necessarily same as number of steps in pipeline!)
+        loaded: false           // Whether or not the sequencer content has been updated for the first time
+    },
+    settings: {             // Various settings to determine the workings of the sequencer
+        content: {
+            width: null,
+            height: null,
+            orientation: "h"
+        },
+        efficientUpdating: true
+    }
+}
+
+
+function IsItemSelected(check, target) {
+    if (check.value) {
+        target.disabled = false;
+    }
+    else {
+        target.disabled = true;
+    }
+}
+
+function IsCheckEnabled(check, target) {
+    if (check.checked) {
+        target.disabled = false;
+        this.removeClass(target, "dis");
+        
+    }
+    else {
+        target.disabled = true;
+        this.addClass(target, "dis");
+    }
+}
+
+function SubmitToolbox(type) {
+    var c = "objectToCreate="+type;
+    var u = "createObject.php";
+    var a = true;
+    var pipeline = document.getElementById("pipelineStringField");
+    var pipelineType = document.getElementById("pipelineTypeField");
+    var pipelineUpdated = document.getElementById("pipelineUpdatedField");
+    document.getElementById("numSteps").value++;
+    
+    newAjaxRequest(c, u, function(result){
+        var resultUid = removeNL(result.responseText);
+        //resultUid.replace("\n","").replace("\r","");
+        
+        pipeline.value += resultUid+",";
+        pipelineType.value += type+",";
+        pipelineUpdated.value += "0,";
+        updateSequencer();
+    }, a);
+}
+
+function selectStep(uid) {
+    /*
+    
+    var nodes = document.getElementById("seqContentWrapper").childNodes;
+    for (var i = 0; i < nodes.length; i++) {     //loop through childNodes. Skip first node (whitespace)
+        if (hasClass(nodes[i], "displayStep")) {    //check if current childNode is a displayStep, not divider or text.
+            if (nodes[i].id == uid) {
+                if (hasClass(nodes[i], "selected")) {
+                    removeClass(nodes[i], "selected");
+                }
+                else {
+                    addClass(nodes[i], "selected");
+                }                
+            }
+            else {
+                removeClass(nodes[i], "selected");
+            }
+        }
+    }
+     */
+    // Hier is een snellere manier voor!
+    var element = document.getElementById(uid);
+    var prevElement = document.getElementById(document.getElementById("selectedStepField").value);
+    
+    if (!element || !hasClass(element, "displayStep")) {
+        return;
+    }
+    // misschien nog checks inbouwen of het echt wel een element is?
+    var selectedStepField = document.getElementById("selectedStepField");
+    if (!hasClass(element, "selected")) {
+        if (prevElement) {
+            removeClass(prevElement, "selected");
+        }
+        addClass(element, "selected");
+        selectedStepField.value = uid;
+        
+        var pl = stringToArray(document.getElementById("pipelineStringField").value, ",");
+        var plType = stringToArray(document.getElementById("pipelineTypeField").value, ",");
+        var type = plType[pl.indexOf(uid)];
+        ajaxInfoRequest(uid, document.getElementById("infoPanelContent"), type);
+        
+        
+    }
+    else {
+        deselectStep(uid);
+    }
+    
+    
+// Update selected step field with uid of currently selected step.
+    
+    
+}
+
+function deleteStep() {
+    // delete an object from the session.
+    // note: does not actually remove the object from the database, only takes it out of the pipeline array.
+        
+    var pl = stringToArray(document.getElementById("pipelineStringField").value, ",");
+    var plType = stringToArray(document.getElementById("pipelineTypeField").value, ",");
+    var plUpdated = stringToArray(document.getElementById("pipelineUpdatedField").value, ",");
+    var selectedStep = document.getElementById("selectedStepField").value;
+    
+    // if no step has been selected, exit the function
+    if (selectedStep == undefined || selectedStep == "") {
+        return;
+    }
+    
+    // find the array index of the specified object uid, then remove it from all three arrays.
+    var index = pl.indexOf(selectedStep);
+    if (index >= 0 && index < pl.length) {
+        pl.splice(index, 1);
+        plType.splice(index, 1);
+        plUpdated.splice(index, 1);
+        // set the updated status of all objects from *index* and forward to "0" (out of date)
+        // this way they will be refreshed the next time updateSequencer(); is called, adn the visual display will match the new pipeline.
+        for (var i = index-1; i < plUpdated.length; i++) {
+            if (i >= 0 ) {
+                plUpdated[i] = "0";
+            }
+        }
+    }
+    
+    document.getElementById("pipelineStringField").value = arrayToString(pl, ",");
+    document.getElementById("pipelineTypeField").value = arrayToString(plType, ",");
+    document.getElementById("pipelineUpdatedField").value = arrayToString(plUpdated, ",");
+    deselectStep(selectedStep);     // Make sure the info panel is up to date as well. (Not showing anything, as it should be...)
+    document.getElementById("numSteps").value--;
+    
+    updateSequencer(false);
+    
+    
+    
+}
+
+function deselectStep(uid) {
+    var field = document.getElementById("selectedStepField");
+    field.value = "";
+    var element = document.getElementById(uid);
+    removeClass(element, "selected");
+    document.getElementById("infoPanelContent").innerHTML = "";
+}
+
+function ajaxStepRequest(UIDS, types) {
+    var c = "uids="+UIDS;
+    if (types != "") {
+        c += "&types="+types;
+    }
+    var u = "returnStep.php";
+    newAjaxRequest(c, u, function(result) {
+        document.getElementById("seqContentWrapper").innerHTML = result.responseText;
+    }, true);
+}
+
+function ajaxInfoRequest(uid, el, type) {
+    var c = "uid="+uid;
+    c += "&type="+type;
+    var u = "getInfo.php";
+    newAjaxRequest(c, u, function(result) {
+        el.innerHTML = result.responseText;
+    }, true);
+}
+
+function drawSteps2() {
+    var content = document.getElementById("seqContentWrapper");
+    var pipeline = document.getElementById("pipelineStringField").value;
+    var pipelineTypes = document.getElementById("pipelineTypeField").value;
+    var numSteps = document.getElementById("numSteps").value;
+    if (numSteps > 0) {
+        pipeline = pipeline.replace(/,/g , ",divider,");    //regex search for commas, global (repeat), to represent them with visual dividers.
+        pipelineTypes = pipelineTypes.replace(/,/g, ",divider,");
+        ajaxStepRequest(pipeline, pipelineTypes);
+    }
+}
+
+function updateSequencer(firstLoad) {
+    // Load hidden field values
+    debugger;
+    var plString = document.getElementById("pipelineStringField").value;
+    var plTypeString = document.getElementById("pipelineTypeField").value;
+    var plUpdatedString = document.getElementById("pipelineUpdatedField").value;
+    var count = document.getElementById("numSteps").value;
+    
+    if (count < 1) {
+        document.getElementById("seqContentWrapper").innerHTML = "";
+        return;
+    }
+    // If this is on page-load time
+    if (firstLoad == true) {
+        var seqContent = document.getElementById("seqContentWrapper");
+        seqContent.innerHTML = "";
+        requestString = plString.slice(0, -1);
+        requestString = requestString.replace(/,/g, ",divider,");
+        newAjaxRequest("uids="+requestString, "returnStep.php", function(result) {
+            seqContent.innerHTML = result.responseText;
+        }, true);
+        
+        plUpdatedString = "";
+        for (var i = 0; i < plString.split(",").length-1; i++) {
+            plUpdatedString += "1,";
+        }
+        
+        document.getElementById("pipelineUpdatedField").value = plUpdatedString;
+    }
+    else {      // if not
+        var pl = stringToArray(plString, ",");    
+        var plType = stringToArray(plTypeString, ",");    
+        var plUpdated = stringToArray(plUpdatedString, ",");
+    
+        var count = pl.length;
+    
+        document.getElementById("numSteps").value = count;
+        var seqContent = document.getElementById("seqContentWrapper");
+        // hier zit een fout. Als er een deleted step nog in de pipeline staat haalt hij de eerste valid step weg ipv een text node.
+        // twee mogelijkheden: 
+        // 1: check of het text node is.
+        // 2: modulo check of het een even aantal steps is. Als alles klopt kan er onmogelijk een even aantal childNodes zijn.
+        if (seqContent.childNodes.length % 2 == 0 && seqContent.childNodes.length > 0) {
+            seqContent.removeChild(seqContent.childNodes[0]);
+            
+        }
+        
+        
+        for (var i = 0; i < pl.length; i++) {   // loop through pipeline contents
+            if (plUpdated[i] == "0") {   // if the element is not up to date
+                // first remove the step representation from the sequencer
+                //timeDiff.setStartTime();
+                
+            
+                // IMPROVISE !!!!!!!!!!
+                var elementByIndex = seqContent.childNodes[2*i];    // works with moved steps
+                var elementById = document.getElementById(pl[i]);   // works with ???, not moved steps though... Keeping this in here for future bugfixing. This value is not currently used.
+                var element = elementByIndex;
+            
+            
+                // END IMPROVISE !!!!!!!!!!!!
+                if (element == null) {
+                    element = document.createElement("div");
+                    element.name = "placeholder";
+                    seqContent.appendChild(element);
+                }
+                if (element.nextSibling) {
+                    var nextElement = element.nextSibling;
+                }
+                else {
+                    var nextElement = document.createElement("div");
+                    nextElement.name = "placeholderNext";
+                    seqContent.appendChild(nextElement);
+                }
+            
+                // now request a new step representation and insert it after previousElement
+                var holderDiv = document.createElement("div");
+                var requestString = "uids="+pl[i];
+            
+                if (plType[i]) {
+                    requestString += "&types="+plType[i];
+                }
+                // globally declare newDiv so it can be passed to the updateDividers function
+                var newDiv;
+            
+                newAjaxRequest(requestString, "returnStep.php", function(result) {
+                    holderDiv.innerHTML = result.responseText;
+                    newDiv = holderDiv.childNodes[1];            
+                    seqContent.replaceChild(newDiv, element);
+                    if (nextElement.name == "placeholderNext") {
+                        seqContent.removeChild(nextElement);
+                    }
+                    plUpdated[i] = "1";
+                }, false);
+            
+                       
+                // ALTERNATIVE METHOD TO REPLACECHILD!!!
+                //seqContent.removeChild(element);
+                //seqContent.insertBefore(newDiv, nextElement);
+            
+                // Now check if dividers are necessary.
+            
+                //alert("INSERT CODE FOR UPDATEDIVIDERS HERE!");
+                //alert(timeDiff.getDiff());
+                
+                // If seqContent contains any further entries when the last pipeline uid has been drawn, these are to be removed.
+                // This happens after the user performs a "delete step" operation and there is now one fewer step in the array than in seqContent.
+                // All steps other than the first and the last are auto-adjusted due to "out of date" flag.
+                if (i >= pl.length - 1) {
+                    
+                    // This is a really complicated way of saying "Delete the next two elements if they exist"
+                    while ((nextElement = newDiv.nextSibling) != undefined) {
+                        seqContent.removeChild(nextElement);
+                    }
+                    
+                }
+                // Do the same check for the first step in the pipeline. 
+                // Is there no more elegant solution for this? For instance, check if a step should be in the pipeline in the first place, else delete it and it's following divider
+                
+                
+                updateDividers(newDiv);
+            }
+        }
+    
+        // afterwards, convert the arrays back to strings and set to appropriate fields
+        var newUpdatedString = arrayToString(plUpdated, ",");
+        document.getElementById("pipelineUpdatedField").value = newUpdatedString;
+    }
+}
+
+function updateDividers (element) {
+    var seqContent = document.getElementById("seqContentWrapper");
+    
+    if (element.nextSibling){
+        var nextElement = element.nextSibling;
+    }
+    if (element.previousSibling) {
+        var previousElement = element.previousSibling;
+    }
+    
+    if (nextElement){
+        if (!hasClass(nextElement, "divider")) {
+            /*var holderDiv = document.createElement("div");
+            newAjaxRequest("uids=divider&types=divider", "returnStep.php", function(result) {
+                holderDiv.innerHTML = result.responseText;
+                var newDivider = holderDiv.childNodes[1];
+                seqContent.insertBefore(newDivider, nextElement);
+            }, false);*/
+            
+            var newDivider = document.createElement("div");
+            newDivider.className = "divider";
+            // set the divider type, depending on orientation of editor
+            // This currently does nothing, because editors haven't been generalized yet and there is no sequencer global var.
+            // Shame on me for including this...
+            if (sequencer.type) {
+                if (sequencer.type.indexOf("v") != -1) {
+                    addClass(newDivider, "vertical");
+                }
+                else if (sequencer.type.indexOf("h") != -1) {
+                    addClass(newDivider, "horizontal");
+                }
+                else {
+            // Do nothing
+            }
+            }
+            seqContent.insertBefore(newDivider, nextElement);
+                        
+        }
+    }
+    
+    if (previousElement){
+        if (!hasClass(previousElement, "divider")) {
+            var holderDiv = document.createElement("div");
+            newAjaxRequest("uids=divider&types=divider", "returnStep.php", function(result) {
+                holderDiv.innerHTML = result.responseText;
+                var newDivider = holderDiv.childNodes[1];
+                seqContent.insertBefore(newDivider, element);
+            }, false);
+        }
+    }
+    
+}
+
+function savePipeline (confirmSave) {
+    if (confirmSave==true) {
+        var answer = confirm("Save changes to pipeline?");
+    }
+    else {
+        var answer = true;
+    }
+    
+    
+    if (answer) {
+        var pipeline = document.getElementById("pipelineStringField").value;
+        pipeline = pipeline.slice(0, pipeline.length - 1);
+        var types = document.getElementById("pipelineTypeField").value;
+        types = types.slice(0, types.length - 1);
+        var session = document.getElementById("sessionField").value;
+        var requestString = "uids="+pipeline+"&types="+types+"&sessionUid="+session;
+        console.log(requestString);
+        
+        
+        var success;
+        newAjaxRequest(requestString, "savesession.php", function(result){
+            success = result.responseText;
+        }, true);
+        console.log(success);
+    }
+}
+
+function t_setOutOfDate() {
+    // if a step is currently selected
+    var uid = document.getElementById("selectedStepField").value;
+    if (uid == "") {
+        alert("No step selected!");
+        return;
+    }
+    
+    // convert to arrays for looping
+    var plString = document.getElementById("pipelineStringField").value;
+    var plTypeString = document.getElementById("pipelineTypeField").value;
+    var plUpdatedString = document.getElementById("pipelineUpdatedField").value;
+    
+    
+    var pl = stringToArray(plString, ",");    
+    var plType = stringToArray(plTypeString, ",");    
+    var plUpdated = stringToArray(plUpdatedString, ",");    
+    
+    // set the targeted element's tag for "Needs updating"
+    plUpdated[pl.indexOf(uid)] = "0";
+    
+    // then rewrite the content strings and set them to the appropriate fields
+    var newUpdatedString = arrayToString(plUpdated, ",");
+    document.getElementById("pipelineUpdatedField").value = newUpdatedString;
+}
+
+function editStep() {
+    // eerst saven, dan de object type zoeken in de typelist, dan redirecten naar de goede pagina
+    savePipeline(false);
+    
+    var pipeline = document.getElementById("pipelineStringField").value;
+    var pipelineTypes = document.getElementById("pipelineTypeField").value;
+    var selectedStep = document.getElementById("selectedStepField").value;
+    pipeline = stringToArray(pipeline, ",");
+    pipelineTypes = stringToArray(pipelineTypes, ",");
+    var stepType = pipelineTypes[pipeline.indexOf(selectedStep)];
+    var postForm = document.createElement("form");
+    postForm.action = stepType.toLowerCase()+"Editor.php";      //redirect to "type"editor.php
+    postForm.method = "POST";
+    var objectUid = document.createElement("input");
+    objectUid.type = "hidden";
+    objectUid.name = "objectUid";
+    objectUid.value = selectedStep;
+    postForm.appendChild(objectUid);
+    postForm.submit();
+}
+
+function moveStep (direction) {
+    // misschien maar eens een loadhiddenfields functie maken voor deze meuk?
+    
+    var selectedStep = document.getElementById("selectedStepField").value;
+    
+    if (selectedStep != undefined && selectedStep != "") {
+        var pipeline = stringToArray(document.getElementById("pipelineStringField").value, ",");
+        var pipelineTypes = stringToArray(document.getElementById("pipelineTypeField").value, ",");
+        var updated = stringToArray(document.getElementById("pipelineUpdatedField").value, ",");
+    }
+    else {
+        alert("No step selected! Unable to move");
+        return;
+    }
+    
+    var id = pipeline.indexOf(selectedStep);
+    if ((id == 0 && direction == -1) || (id == pipeline.length-1 && direction == 1)){
+        alert("Cannot move out of bounds!");
+        return;
+    }
+    var tempString = pipeline[id], tempType = pipelineTypes[id];
+    
+    pipeline[id] = pipeline[id+direction];
+    pipelineTypes[id] = pipelineTypes[id+direction];
+    pipeline[id+direction] = tempString;
+    pipelineTypes[id+direction] = tempType;
+    updated[id] = "0";
+    updated[id+direction] = "0";
+    
+    pipeline = arrayToString(pipeline, ",");
+    pipelineTypes = arrayToString(pipelineTypes, ",");
+    updated = arrayToString(updated, ",");
+    
+    document.getElementById("pipelineStringField").value = pipeline;
+    document.getElementById("pipelineTypeField").value = pipelineTypes;
+    document.getElementById("pipelineUpdatedField").value = updated;
+    updateSequencer();
+    
+    // Then reselect the previously selected step
+    addClass(document.getElementById(selectedStep), "selected");
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /Dev/trunk/js/surveyEditorScripts.js
===================================================================
--- /Dev/trunk/js/surveyEditorScripts.js	(revision 180)
+++ /Dev/trunk/js/surveyEditorScripts.js	(revision 181)
@@ -39,6 +39,4 @@
     return s;
 }
-
-
 
 function loadSurvey() {
Index: /Dev/trunk/returnStep.php
===================================================================
--- /Dev/trunk/returnStep.php	(revision 180)
+++ /Dev/trunk/returnStep.php	(revision 181)
@@ -130,5 +130,5 @@
 
 //echo out the HTML markup
-        $responsePart = '<div class="displayStep" id="' . $result->uid . '" onClick="selectStep(this.id);"><div class="displayStepIcon"><img src="' . $imageURL . '" /></div>' . $result->title . '</div>';
+        $responsePart = '<div class="displayStep" id="' . $result->uid . '" onClick="clickStep(this.id);"><div class="displayStepIcon"><img src="' . $imageURL . '" /></div>' . $result->title . '</div>';
         return $responsePart;
     }
