Index: Dev/branches/jos-branch/js/generalScripts.js
===================================================================
--- Dev/branches/jos-branch/js/generalScripts.js	(revision 236)
+++ Dev/branches/jos-branch/js/generalScripts.js	(revision 237)
@@ -163,4 +163,22 @@
             posX += element.offsetLeft;
             posY += element.offsetTop;
+        } while (element = element.offsetParent);
+    }
+    
+    var result = {
+        X: posX,
+        Y: posY
+    }
+    return result;
+}
+
+// TODO: this is a broken version of the above function, to be used during the demo ONLY! (Else the dropdown menu does not work correctly...
+// Fix/remove as soon as possible
+function getWrongPos(element) {
+    var posX = posY = 0;
+    if (element.offsetParent) {
+        do {
+            posX += element.offsetLeft;
+            posY += element.offsetTop;
         } while (element = element.offSetParent);
     }
@@ -184,4 +202,5 @@
 
 // Drop down menu implementation. Supports three levels: Base button, 1st level categories, and 2nd level links
+// TODO: getPos functie werkte eerst niet goed, menu offset is nog beetje whack. Betere manier van dropdown menu vinden en voor nu even de getPos functie stuk laten?
 function DDMenu() {
     // Initialize function, setting all needed variables.
@@ -227,5 +246,5 @@
         instance.ddMenuItem = ge(id);
         instance.ddMenuItem.style.visibility = "visible";
-        var parentPos = getPos(instance.ddMenuItem.parentNode);
+        var parentPos = getWrongPos(instance.ddMenuItem.parentNode);
         var parentWidth = getWidth(instance.ddMenuItem.parentNode);
         instance.ddMenuItem.style.left = (parentPos.X + parentWidth)+"px";
@@ -252,2 +271,20 @@
     }
 }
+
+function manualEventFire(element, rawEvent) {
+    // Attempts to fire a raw DOM event on an element
+    
+    try {
+        element = document.getElementById(element);
+        if (element.fireEvent) {
+            element.fireEvent("on"+rawEvent.type, rawEvent);
+            return true;
+        }
+        else if (element.dispatchEvent) {
+            element.dispatchEvent(rawEvent);
+            return true;
+        }
+    } catch (e) {
+    }
+    return false;
+}
Index: Dev/branches/jos-branch/js/questionEditorScripts.js
===================================================================
--- Dev/branches/jos-branch/js/questionEditorScripts.js	(revision 236)
+++ Dev/branches/jos-branch/js/questionEditorScripts.js	(revision 237)
@@ -21,18 +21,4 @@
 }
 
-function updateIdentifier() {
-    var identField = document.getElementById("questionIdentifierField");
-    if (identField.value == undefined && identField.value == "") {
-        return;
-    }
-    var headerField = document.getElementById("header_identifier");
-    headerField.innerHTML = identField.value;
-}
-
-
-//////////////////////////////////////////
-/* QUESTION EDITOR CLASS BASED APPROACH */
-//////////////////////////////////////////
-
 function QuestionEditor() {
     // Properties    
@@ -47,5 +33,41 @@
     // Basic functionality
     this.setValues = function(arguments) {
-        var question = JSON.parse(arguments);        
+        debugger;
+        var question = JSON.parse(arguments)[0];
+        var qeTypeField = ge("qeTypeField");
+        ge("qeCodeField").value = question.code;
+        ge("qeBodyTextField").value = question.description;
+        switch (question.type.toLowerCase()) {
+            case "int":
+                // First make sure all the necessary fields are present
+                me.type_Integer();
+                // Then fill them in using the available data
+                qeTypeField.value = "int";
+                ge("qeMinValueField").value = question.minValue;
+                ge("qeMaxValueField").value = question.maxValue;
+                break;
+            case "scale":
+                me.type_Scale();
+                qeTypeField.value = "scale";
+                ge("qeNumChoicesField").value = question.numChoices;
+                ge("qeLegendsEnabledField").checked = question.legendsEnabled;
+                ge("qeLowerLegendField").value = question.lowerLegend;
+                ge("qeUpperLegendField").value = question.upperLegend;
+                break;
+            case "choice":
+                me.type_Choice();
+                qeTypeField.value = "choice";
+                ge("qeNumOptionsFIeld").value = question.numOptions;
+                ge("qeMultipleAnswersField").value = question.multipleAnswers;
+                // then some more to add textboxes (qeParamAnswerGroup) for all the possble choices.
+                // Maybe a central version that appends these groups/textinputs? Maybe not, though. Don't want stuff too abstracted...
+                break;
+            case "text":
+                me.type_Text();
+                qeTypeField.value = "text";
+                ge("qeTextMaxLengthField").value = question.maxTextLength;
+                break;
+                
+        }
     }
     this.init = function() {
@@ -150,6 +172,7 @@
     this.save = function() {
         var request = {
-            "title": ge("qeTitleField").value,
-            "type": ge("qeTypeField").value
+            "title": ge("qeTitleField").innerHTML, 
+            "code": ge("qeCodeField").value, 
+            "description": ge("qeBodyTextField").value
         }
         
@@ -158,5 +181,8 @@
                 request.answerType = "int";
                 request.minValue = parseInt(ge("qeMinValueField").value);
+                if (request.minValue == "NaN") request.minValue = -1;   // Is this the correct way to do this?
                 request.maxValue = parseInt(ge("qeMaxValueField").value);
+                if (request.maxValue == "NaN") request.maxValue = -1;
+                // Include error checking and form validation!!
                 break;
             case "scale":
@@ -166,16 +192,64 @@
                 request.lowerLegend = ge("qeLowerLegendField").value;
                 request.upperLegend = ge("qeUpperLegendField").value;
+                // Include error checking and form validation!!
                 break;
             case "choice":
                 request.answerType = "choice";
+                request.multipleAnswers = ge("qeMultipleAnswersField").checked;
+                request.possibleAnswers = array();
+                var answerFieldset = ge("qeParamsAnswerFieldset");
+                var count = ge("qeNumOptionsField").value;
+                
+                for (var i = 0; i < count; i++) {
+                    var el = ge("qeAnswerField"+i);
+                    request.possibleAnswers.push(el.value);
+                }
+                // Include error checking and form validation!!
                 break;
             case "text":
                 request.answerType = "text";
-                break;
-        }
-        
-        newAjaxRequest(requestString, "createObject.php", function(result){
-            // Display a success message, or throw an error.
-            }, true);
+                request.maxTextLength = ge("qeTextMaxLength").value;
+                // Include error checking and form validation!!
+                break;
+        }
+        
+        requestString = "args="+JSON.stringify(request);
+        
+        newAjaxRequest(requestString, "setQuestion.php", function(result){
+            // Then add the returned uid, if existing, to the sequencer.survey.questions array and set it for update
+            debugger;
+            var response = JSON.parse(result.responseText);
+            console.log(response);
+            if (response.created == true) {
+                if (response.uid) {
+                    // Created a new question, add it to the sequencer content array and set it for an update
+                    sequencer.survey.questions.uids.push(response.uid);
+                    sequencer.survey.questions.upToDate.push(false);
+                }
+                else {
+                    alert("ERROR!");
+                }
+            } else {
+                if (response.uid){
+                    // Edited an existing question that was already in the sequencer content. Set it for an update
+                    sequencer.survey.questions.upToDate[sequencer.survey.questions.uids.indexOf(response.uid)] = false;
+                }
+                else {
+                    alert("ERROR!");
+                }
+            }
+            
+            
+            // Then remove the editor from the sequencer content, so that it can be replaced with the correct question view.
+            me.element.parentNode.removeChild(me.element);
+            sequencer.state.editing = false;
+            updateSequencer();
+        }, true);
+    }
+    this.discard = function() {
+        me.element.parentNode.removeChild(me.element);
+        me.init();
+        sequencer.state.loaded = true;
+        sequencer.state.editing = false;
     }
     this.reset = function() {
@@ -340,5 +414,4 @@
     }
     this.type_Choice_CheckAnswerFields = function() {
-        debugger;
         var container = ge("qeParamsAnswerFieldset");
         var numAnswers = parseInt(document.getElementById("qeNumOptionsField").value, 10);
@@ -358,5 +431,5 @@
             // Extra inputs need to be added
             var n = numAnswers - numAnswerFields;
-            for (var x = 0; x < n; x++) {
+            for (var x = 1; x < n+1; x++) {
                 var group = ce("div");
                 group.className = "qeChoiceAnswerGroup";
@@ -387,18 +460,24 @@
     // Editing
     this.editQuestion = function(uid) {
+        debugger;
         if (sequencer.state.editing == true) return;
         if (sequencer.state.loaded == false) return;
         sequencer.state.editing = true;
-        
-        var request = {
-            "type": "Question",
-            "uid": uid
-        }
-        
+        sequencer.state.loaded = false;
+        
+        var request = new Array({
+            type: "Question",
+            uid: uid
+        });
+        me.init();
+        var oldElement = ge(uid);
+        if (oldElement) {
+            // There really should be.... I don't know why I am doing this check...
+            oldElement.parentNode.replaceChild(me.element, oldElement);
+        }
         var requestString = "args="+JSON.stringify(request);
-        sequencer.state.loaded = false;
-        newAjaxRequest(requestString, getObject.php, function(result){
+        newAjaxRequest(requestString, "getObject.php", function(result){
             // Once results are in
-            questionEditor.setValues(result.responseText);
+            me.setValues(result.responseText);
             sequencer.state.loaded = true;
         }, true);
@@ -406,5 +485,5 @@
     this.createNewQuestion = function() {
         if (sequencer.state.editing == true) return;
-        if (sequencer.state.loading == true) return;
+        if (sequencer.state.loading == false) return;
         sequencer.state.editing = true;
     
@@ -414,2 +493,9 @@
     }
 }
+
+// IT LIIIIIIVESSSSS
+// TODO: Add database fields for all the necessary question parameters. Maybe only one question parameter property that holds all the settings, then read it out in javascript?
+// Why have a question Description? Is this even necessary?
+// Needed properties:
+// Also not exactly sure what "question->category" is for. Is this one of those questionSet things that Julia was talking about?
+// 
Index: Dev/branches/jos-branch/js/sequencerScripts.js
===================================================================
--- Dev/branches/jos-branch/js/sequencerScripts.js	(revision 236)
+++ Dev/branches/jos-branch/js/sequencerScripts.js	(revision 237)
@@ -123,4 +123,30 @@
 }
 
+function setSequencerSize() {
+    var seqContent = ge("seqContent");
+    switch (sequencer.settings.content.orientation.toLowerCase()) {
+        case "vertical":
+            var availHeight = window.innerHeight;
+            var yOffset = getPos(seqContent).Y;
+            var bottomControlsHeight = 36;
+            var bottomMargin = 12;
+            sequencer.settings.content.height = (availHeight - yOffset - bottomControlsHeight - bottomMargin);
+            sequencer.settings.content.width = 665;
+            seqContent.style.height = sequencer.settings.content.height+"px";
+            seqContent.style.width = sequencer.settings.content.width+"px";
+            addClass(seqContent, "vertical");
+            break;
+        case "horizontal":
+            sequencer.settings.content.width = 800;
+            sequencer.settings.content.height = 125;
+            seqContent.style.height = sequencer.settings.content.height+"px";
+            seqContent.style.width = sequencer.settings.content.width+"px";
+            addClass(seqContent, "horizontal");
+            break;
+        default:
+            break;
+    }
+}
+
 function initSequencer() {
     // Called from loadSequencer(). Sets sequencer.settings properties depending on content type and values passed by PHP in hidden fields (currently only one), then removes these fields.
@@ -129,26 +155,12 @@
     // load settings fields first
     var fContentType = ge("sContentTypeField");
-    var content = ge("seqContent");
-    //sequencer.settings.content.contentType = fContentType.value.toLowerCase();
     sequencer.settings.content.contentType = fContentType.value;
     //Then select settings from a few presets
-    
     switch (sequencer.settings.content.contentType.toLowerCase()) {
         case "session":
             sequencer.settings.content.orientation = "horizontal";
-            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";
-            addClass(content, "horizontal");
             break;
         case "survey":
             sequencer.settings.content.orientation = "vertical";
-            sequencer.settings.content.width = 650;     //guesstimated
-            var roomH = screen.availHeight;
-            sequencer.settings.content.height = roomH - 200;
-            content.style.width = sequencer.settings.content.width+"px";
-            content.style.height = sequencer.settings.content.height+"px";
-            addClass(content, "vertical");
             break;
         default:
@@ -156,4 +168,6 @@
     }
     fContentType.parentNode.parentNode.removeChild(fContentType.parentNode);
+    
+    window.addEventListener("load", setSequencerSize, true);
 }
 
@@ -230,5 +244,5 @@
         requestString = "args="+JSON.stringify(args);
         newAjaxRequest(requestString, "returnObjectDisplay.php", function(result){
-            console.log(result.responseText);
+            //console.log(result.responseText);
             insertNewObjects(result.responseText, needsUpdating);
         }, true);
@@ -279,5 +293,5 @@
         requestString = "args="+JSON.stringify(args);
         newAjaxRequest(requestString, "returnObjectDisplay.php", function(result){
-            console.log(result.responseText);
+            //console.log(result.responseText);
             content.removeChild(loadingGif);
             insertNewObjects(result.responseText, needsUpdating);
@@ -392,5 +406,5 @@
     //console.log(responseText);
     // Container function that calls different insertNewX() functions depending on content type. Called from updateSequencer().
-    console.log(responseText);
+    //console.log(responseText);
     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.
@@ -416,5 +430,5 @@
         
     newAjaxRequest(c, u, function(result) {
-        console.log(result.responseText);
+        //console.log(result.responseText);
         sequencer.survey.questions.uids.push(removeNL(result.responseText));
         sequencer.survey.questions.upToDate.push(false);
@@ -434,5 +448,5 @@
          */
     if (!response || !response.length > 0) return;
-    console.log(response);
+    //console.log(response);
     
     var content = ge("seqContentWrapper");
@@ -524,4 +538,6 @@
 
 function insertNewQuestions(response, needsUpdating) {
+    //TODO: QuestionDisplay ook classbased maken zoals de questionEditor?
+    
     //Code that inserts or replaces new object displays in the sequencer. Question version.
     var content = ge("seqContentWrapper");
@@ -571,8 +587,19 @@
         removeButton.className = "smallButton";
         editButton.addEventListener("click", function(e){
-            alert('Editing not yet supported!');
+            var targ;
+            if (!e) e = window.event;
+            if (e.target) targ = e.target;
+            else if (e.srcElement) targ = e.srcElement;
+            
+            do {
+                targ = targ.parentNode;
+            } while (!hasClass(targ, "question"));
+            
+            questionEditor.editQuestion(targ.id);
+            e.stopPropagation();
         }, false);
         removeButton.addEventListener("click", function(e){
             alert('Removing not yet supported!');
+            e.stopPropagation();
         }, false);
         controlsDiv.appendChild(editButton);
@@ -596,5 +623,17 @@
             }
             else {
-                content.replaceChild(frameDiv, content.childNodes[needsUpdating[j][0]*2]);
+                if (content.childNodes[needsUpdating[j][0]*2]) {
+                    content.replaceChild(frameDiv, content.childNodes[needsUpdating[j][0]*2]);
+                }
+                else {
+                    content.appendChild(frameDiv);
+                    // HACK TIME!
+                    for (var s = 0; s < content.childNodes.length; s++) {
+                        if (hasClass(content.childNodes[s], "loading")) {
+                            content.childNodes[s].parentNode.removeChild(content.childNodes[s]);
+                        }
+                    }
+                    // Serieus, dit moet beter...
+                }
             }
             sequencer.survey.questions.upToDate[needsUpdating[j][0]] = true;
@@ -622,5 +661,5 @@
             request.questions.uids = sequencer.survey.questions.uids;
             requestString = "args="+JSON.stringify(request);
-            console.log(request);
+            //console.log(request);
             newAjaxRequest(requestString, url, function(result){
                 console.log(result.responseText);
@@ -658,5 +697,5 @@
 function selectStep(uid) {
     // Called from clickStep(), manages CSS class assignment and updating of state variables. Also calls for info panel update.
-    
+    debugger;
     var element = ge(uid);
     if (element) {
@@ -674,5 +713,5 @@
                 break;
         }
-        (type != "survey") ? ajaxInfoRequest(uid, ge("infoPanelContent"), type) : type=type /*This does nothing*/;
+        (type != "Question") ? ajaxInfoRequest(uid, ge("infoPanelContent"), type) : type=type /*This does nothing*/;
         sequencer.state.selectedObject.uid = uid;
         sequencer.state.selectedObject.index = null;  //Don't know how to do this yet.
@@ -718,8 +757,8 @@
     requestString += "&sessionUid=";
     requestString += sequencer.session.uid;
-    console.log(requestString);
+    //console.log(requestString);
     newAjaxRequest(requestString, "savesession.php", function(result){
-        console.log(result.responseText);
-    }, true);
+        //console.log(result.responseText);
+        }, true);
 }
 
