source: Dev/trunk/classes/QuestionCreationTool.php @ 116

Last change on this file since 116 was 116, checked in by fpvanagthoven, 14 years ago

Some refactoring and commenting, plus, the questions within the categories in QuestionCreationTool? are now sorted aswell; on code.

File size: 22.2 KB
RevLine 
[102]1<?php
2
3/**
4 * Tool that displays a list and an edit panel
5 *
6 * @author fpvanagthoven
7 */
8class QuestionCreationTool {
[115]9
[114]10    private $questions;
[102]11
[114]12    public function __construct($questions) {
13        $this->questions = $questions;
[116]14
15        $this->loadQuestionsToJavascript();
[103]16        $this->javascript();
[102]17        $this->displayList();
18        $this->displayEditPanel();
19    }
[116]20   
21    /**
22     * Loads the questions that PHP retrieved from database
23     * into javascript. This is done so that the page does not need
24     * to refresh in order to load an entire question in to the form.
25     */
26    private function loadQuestionsToJavascript()
27    {
28       
29    }
[102]30
[103]31    private function javascript() {
32        ?>
33        <script type="text/javascript">
34            function handleType(select)
35            {
36                var type = select.valueOf().value;
37                clearSpecifications();
[116]38                                                                                                       
[103]39                /* set answerCount for options */
40                document.getElementById("answerSpecifications").answerCount = 1;
[116]41                                                                                                       
[103]42                switch (type) {
43                    case "text":
44                        break;
45                    case "mc":
46                        addOption();
47                        break;
48                    case "int":
49                        minMax();
50                        break;
51                    case "checkboxes":
52                        addOption();
53                        break;
54                    case "scale":
55                        minMaxIncr();
56                        break;
57                    default:
[116]58                                                                                                               
[103]59                        break;
60                }
61
62            }
[116]63                                                                                                   
[103]64            function clearSpecifications()
65            {
66                var specs = document.getElementById("answerSpecifications");
67                specs.innerHTML = "";
68                specs.clicked = null;
69                specs.lastAnswer = null;
[116]70                                                                                       
[103]71                var questionType = document.getElementById("questionType");
72                var buttons = document.getElementById("questionButtons");
73                if(buttons != null)
74                    questionType.removeChild(buttons);
75            }
[116]76                                                                                                   
[103]77            function addOption()
78            {                       
79                var specs = document.getElementById("answerSpecifications");
[116]80                                                                                                       
[103]81                addAddRemoveOptionButtonsOnce(specs);
82                addAnswerInput(specs);
[116]83                                                                                                       
[103]84            }
[116]85                                                                                                   
[103]86            function removeOption()
87            {
88                var specs = document.getElementById("answerSpecifications");
[116]89                                                                                                       
[103]90                if(specs.lastAnswer.prev != null)
91                {
92                    specs.removeChild(specs.lastAnswer);
93                    specs.lastAnswer = specs.lastAnswer.prev;
94                    specs.answerCount--;
95                }
96            }
[116]97                                                                                                   
[103]98            function addAnswerInput(specs)
99            {
100                var answerCount = specs.answerCount;
[116]101                                                                                                       
[103]102                /* set value for option textbox */
103                var optionStr = "Option " + answerCount;
[116]104                                                                                                       
[103]105                /* the input textbox */
106                var answerInput = document.createElement("input");
107                answerInput.setAttribute("type", "text");
108                answerInput.setAttribute("name", "ans" + answerCount);
109                answerInput.setAttribute("value", optionStr);
110                answerInput.className = "answerInput";
[116]111                                                                                                       
[103]112                specs.appendChild(answerInput);
[116]113                                                                                                       
[103]114                /* Singly linked list */
115                answerInput.prev = specs.lastAnswer; // remember last one
116                specs.lastAnswer = answerInput; // new lastAnswer
[116]117                                                                                                       
[103]118                specs.answerCount++;               
119            }
[116]120                                                                                                   
[103]121            function addAddRemoveOptionButtonsOnce(specs)
122            {
123                if (specs.clicked == null)
124                {
125                    var buttonsDiv = document.createElement("div");
126                    buttonsDiv.id = "questionButtons";
127                    buttonsDiv.style.display = "inline";
128                    var typeBox = document.getElementById("questionType");
129                    typeBox.appendChild(buttonsDiv);
[116]130                                                                                           
[103]131                    addAddOptionButton(buttonsDiv);                                 
132                    addRemoveOptionButton(buttonsDiv);
[116]133                                                                                                           
[103]134                    specs.clicked = true;
135                }
136            }
[116]137                                                                                                   
[103]138            function addAddOptionButton(buttonsDiv)
139            {   
140                var addOpt = document.createElement("input");
141                addOpt.setAttribute("type", "button");
142                addOpt.setAttribute("id", "addOpt");
143                addOpt.setAttribute("class", "surveyButton");
144                addOpt.setAttribute("onclick", "addOption()");
145                addOpt.setAttribute("value", "Add Option");
146                buttonsDiv.appendChild(addOpt);                                 
147            }
[116]148                                                                                                   
[103]149            function addRemoveOptionButton(buttonsDiv)
150            {
151                var removeOpt = document.createElement("input");
152                removeOpt.setAttribute("type", "button");
153                removeOpt.className = "surveyButton";
154                removeOpt.setAttribute("onclick", "removeOption()");
155                removeOpt.setAttribute("value", "x");
156                buttonsDiv.appendChild(removeOpt);
157            }
[116]158                                                                                                   
[103]159            function minMax(min, max)
160            {
161                if (min == null)
162                    var min = '';
163                if (max == null)
164                    var max = '';
[116]165                                                                                                                                                                                                                                                                                                                               
[103]166                var specs = document.getElementById("answerSpecifications");
[116]167                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
[103]168                var answerDiv = document.createElement("div");
[116]169                                                                                                                                                                                                                                                                                                                                                                                                                                       
[103]170                answerDiv.className = "answerDiv";
171                answerDiv.innerHTML = "<label for='min'>Min</label><input type='text' class='intBox' onchange='checkInt(this)' value='" + min + "' name='ans1' />" +
172                    "<label for='max'>Max</label><input type='text' class='intBox' onchange='checkInt(this)' value='" + max + "' name='ans2' />";
[116]173                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
[103]174                specs.appendChild(answerDiv);
175            }     
[116]176                                                                           
[103]177            function checkInt(input)
178            {
179                input.style.borderWidth = '1px' ;
180                var value = input.value;
181                if (isNaN(value))
182                {
183                    input.style.borderColor = 'red';
184                    input.checkPassed = 'no';
185                }
186                else
187                {
188                    input.style.border = '1px solid #888;';
189                    input.checkPassed = null;
190                }
191            }
[116]192                                                           
[103]193            function minMaxIncr(left, right, incr)
194            {
195                if (left == null)
196                    var left = '';
197                else
198                    left.replace("'", "&#39;");
199                if (right == null)
200                    var right = '';
201                else
202                    right.replace("'", "&#39;");
203                if (incr == null)
204                    var incr = '';
[116]205                                                                                                                                                                                                                                                       
[103]206                var specs = document.getElementById("answerSpecifications");
[116]207                                                                                                                                                                                                                                                                                                                                                                                                                                               
[103]208                var answerDiv = document.createElement("div");
209                answerDiv.className = "answerDiv";
[116]210                                                                                                                                                                               
[103]211                var leftLabel = document.createElement("label");
212                var rightLabel = document.createElement("label");
213                var scaleLabel = document.createElement("label");
214                leftLabel.innerHTML = "Left label";
215                rightLabel.innerHTML = "Right label";
216                scaleLabel.innerHTML = "Scale count";
[116]217                                                                                                                                                                               
[103]218                var leftInput = document.createElement("input");
219                leftInput.type = "text";
220                leftInput.value = left;
221                leftInput.name= "ans1";
222                leftInput.setAttribute("onchange", "handleAnswerChange()");
[116]223                                                                                                                                                                               
[103]224                var rightInput = document.createElement("input");
225                rightInput.type = "text";
226                rightInput.value = right;
227                rightInput.name = "ans2";
228                rightInput.setAttribute("onchange", "handleAnswerChange()");
[116]229                                                                                                                                                                               
[103]230                var scaleInput = document.createElement("input");
231                scaleInput.type = "text";
232                scaleInput.className = "intBox";
233                scaleInput.value = incr;
234                scaleInput.setAttribute("onblur", "checkInt(this)");
235                scaleInput.setAttribute("onchange", "");
236                scaleInput.name = "ans3";
[116]237                                                                                                                                                                               
[103]238                answerDiv.appendChild(leftLabel);
239                answerDiv.appendChild(leftInput);
240                answerDiv.appendChild(rightLabel);
241                answerDiv.appendChild(rightInput);
242                answerDiv.appendChild(scaleLabel);
243                answerDiv.appendChild(scaleInput);
[116]244                                                                                                                                                                                                                                                                                                                                                                                                                           
[103]245                specs.appendChild(answerDiv);
[108]246            }   
[116]247                                           
[108]248            function newCategory()
249            {
250                var categoryBox = document.getElementById("categoryBox");
251                categoryBox.innerHTML = "";
[116]252                                               
[108]253                var categoryInput = document.createElement("input");
254                categoryInput.name = "questionCategory";
[116]255                                               
[108]256                categoryBox.appendChild(categoryInput);
257            }
[116]258                                                       
[112]259            function clearFields()
260            {
261                clearCategory();
262                clearCode();
263                clearTitle();
264                clearDescription();
265                clearType();
266            }
[116]267                                           
[112]268            function clearCategory()
269            {
270                var categoryBox = document.getElementById("categoryBox");
271                categoryBox.innerHTML = "";
[116]272                                               
[112]273                var questionCategorySelect = document.createElement("select");
274                questionCategorySelect.setAttribute("name", "questionCategory");
275                questionCategorySelect.id = "questionCategorySelect";
[116]276                                               
[112]277                var newCategoryButton = document.createElement("input");
278                newCategoryButton.setAttribute("type", "button");
279                newCategoryButton.setAttribute("onclick", "newCategory()");
280                newCategoryButton.setAttribute("value", "New Category");
281                newCategoryButton.className = "surveyButton";
[116]282                                               
[112]283                categoryBox.appendChild(questionCategorySelect);
284                categoryBox.appendChild(newCategoryButton);
285            }
[116]286                                           
[112]287            function clearCode()
288            {
289                var codeInput = document.getElementById("questionCode");
290                codeInput.value = "";
291            }
[116]292                                           
[112]293            function clearTitle()
294            {
295                var titleInput = document.getElementById("questionTitle");
296                titleInput.value ="";
297            }
[116]298                                           
[112]299            function clearDescription()
300            {
301                var descriptionInput = document.getElementById("questionDescription");
302                descriptionInput.value = "";
303            }
[116]304                                           
[112]305            function clearType()
306            {
307                var typeSelect = document.getElementById("questionTypeSelect");
308                typeSelect.selectedIndex = 0;
[114]309                clearSpecifications();
[112]310            }
[116]311                                           
[103]312        </script>
313        <?php
314    }
315
[102]316    private function displayList() {
317        ?>
318        <div id="questionListWrapper">
[103]319            <select id="questionsList" size="9999">
[116]320                <?php $this->populateList(); ?>
[102]321            </select>
322        </div>
323        <?php
324    }
325
326    private function displayEditPanel() {
327        ?>
[104]328        <div id="questionCreation" class="floatLeft">
[116]329            <?php $this->displayForm(); ?>
[102]330        </div>
331        <?php
332    }
333
[104]334    private function displayForm() {
335        ?>
336        <form id="questionEditForm" method="post" action="" onsubmit="">
337            <table class="questionTable">
338                <tr>
[108]339                    <td><label for="questionCategory">Category</label></td>
340                    <td id="categoryBox"><!-- Select should be filled with existing categories-->
[116]341                        <?php $this->questionCategorySelect(); ?>
[108]342                    </td>
343                </tr>
344                <tr>
[104]345                    <td><label for="questionCode">Code</label></td>
346                    <td><input id="questionCode" name="questionCode" size="5" /></td>
347                </tr>
348                <tr>
349                    <td><label for="questionTitle">Title</label></td>
[108]350                    <td><input id="questionTitle" name="questionTitle" size="60" /></td>
[104]351                </tr>
352                <tr>
353                    <td><label for="questionDescription">Description</label></td>
354                    <td><input id="questionDescription" name="questionDescription" size="60" /></td>
355                </tr>
356                <tr>
357                    <td><label for="questionType">Type answer</label></td>
358                    <td id="questionType">
[112]359                        <select id="questionTypeSelect" name="questionType" onchange="handleType(this)">
[104]360                            <option value='text' selected='selected'>Text</option>
361                            <option value='int'>Integer</option>
362                            <option value='mc'>Multiple choice</option>
363                            <option value='checkboxes'>Checkboxes</option>
364                            <option value='scale'>Scale</option>
365                        </select>
366                    </td>
367                </tr>
368            </table>
369            <div id="answerSpecifications"></div>
[112]370            <input id="clearQuestionFields" type="button" onclick="clearFields()" class="surveyButton" value="Clear" />
[104]371            <input id="saveQuestion" type="submit" class="surveyButton" value="Save" />
372        </form>
373        <?php
374    }
[115]375
376    private function questionCategorySelect() {
377        ?>
378        <select id="questionCategorySelect" name="questionCategory">
379            <option value='Uncategorized' selected='selected'>Uncategorized</option>
380            <?php $this->generateCategoryOptions(); ?>
381        </select>
382        <!-- New category button -->
383        <input type="button" class="surveyButton" onclick="newCategory()" value="New Category" />
384        <?php
385    }
[116]386
387    private function generateCategoryOptions() {
[115]388        $categories = array();
[116]389
[115]390        foreach ($this->questions as $question) {
391            $category = $question->category;
[116]392            array_push($categories, $category);
[115]393        }
[116]394        $categories = array_unique($categories);
395
[115]396        // You might want to escape quotes and stuff here
397        foreach ($categories as $category) {
[114]398            ?>
[116]399            <option value="<?php echo $category; ?>"><?php echo $category; ?></option>
400            <?php
[114]401        }
402    }
[104]403
[116]404    /**
405     * Populates the question list. Sorts the list first by question category.
406     */
[115]407    private function populateList() {
[116]408
409        $this->questions = $this->sortByCategory($this->questions);
410
411        $currentCategory = null;
412
[115]413        foreach ($this->questions as $question) {
[116]414            if (is_null($currentCategory)) {
415                ?> <optgroup label="<?php echo $question->category; ?>"><?php
416                $currentCategory = $question->category;
417            } else if ($currentCategory != $question->category) {
418                /* Next category */
419                ?></optgroup><?php
420                $currentCategory = $question->category;
421                ?> <optgroup label="<?php echo $question->category; ?>"><?php
422            }
[115]423            ?>
[116]424                /* function loadQuestionIn() should still be made */
425                <option value="<?php echo $question->code; ?>" onfocus="loadQuestionIn()">
426                    <?php echo "[" . $question->code . "] " . $question->title; ?>
427                </option>
428
[115]429                <?php
430            }
[116]431            ?></optgroup><?php
432    }
[115]433
[116]434    /**
435     *
436     * @param type $questions
437     */
438    private function sortByCategory($questions) {
439        usort($questions, "cmp");
440        return $questions;
[115]441    }
[116]442
443}
444
445/* This function is placed outside the class on purpose.
446 * It's only used as callback function.
447 */
448
449function cmp($q1, $q2) {
450    if ($q1->category == $q2->category) {
451        if($q1->code < $q2->code)
452            return -1;
453        else
454            return 1;
455    }
456    return ($q1->category < $q2->category) ? -1 : 1;
457}
[115]458    ?>
Note: See TracBrowser for help on using the repository browser.