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
Line 
1<?php
2
3/**
4 * Tool that displays a list and an edit panel
5 *
6 * @author fpvanagthoven
7 */
8class QuestionCreationTool {
9
10    private $questions;
11
12    public function __construct($questions) {
13        $this->questions = $questions;
14
15        $this->loadQuestionsToJavascript();
16        $this->javascript();
17        $this->displayList();
18        $this->displayEditPanel();
19    }
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    }
30
31    private function javascript() {
32        ?>
33        <script type="text/javascript">
34            function handleType(select)
35            {
36                var type = select.valueOf().value;
37                clearSpecifications();
38                                                                                                       
39                /* set answerCount for options */
40                document.getElementById("answerSpecifications").answerCount = 1;
41                                                                                                       
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:
58                                                                                                               
59                        break;
60                }
61
62            }
63                                                                                                   
64            function clearSpecifications()
65            {
66                var specs = document.getElementById("answerSpecifications");
67                specs.innerHTML = "";
68                specs.clicked = null;
69                specs.lastAnswer = null;
70                                                                                       
71                var questionType = document.getElementById("questionType");
72                var buttons = document.getElementById("questionButtons");
73                if(buttons != null)
74                    questionType.removeChild(buttons);
75            }
76                                                                                                   
77            function addOption()
78            {                       
79                var specs = document.getElementById("answerSpecifications");
80                                                                                                       
81                addAddRemoveOptionButtonsOnce(specs);
82                addAnswerInput(specs);
83                                                                                                       
84            }
85                                                                                                   
86            function removeOption()
87            {
88                var specs = document.getElementById("answerSpecifications");
89                                                                                                       
90                if(specs.lastAnswer.prev != null)
91                {
92                    specs.removeChild(specs.lastAnswer);
93                    specs.lastAnswer = specs.lastAnswer.prev;
94                    specs.answerCount--;
95                }
96            }
97                                                                                                   
98            function addAnswerInput(specs)
99            {
100                var answerCount = specs.answerCount;
101                                                                                                       
102                /* set value for option textbox */
103                var optionStr = "Option " + answerCount;
104                                                                                                       
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";
111                                                                                                       
112                specs.appendChild(answerInput);
113                                                                                                       
114                /* Singly linked list */
115                answerInput.prev = specs.lastAnswer; // remember last one
116                specs.lastAnswer = answerInput; // new lastAnswer
117                                                                                                       
118                specs.answerCount++;               
119            }
120                                                                                                   
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);
130                                                                                           
131                    addAddOptionButton(buttonsDiv);                                 
132                    addRemoveOptionButton(buttonsDiv);
133                                                                                                           
134                    specs.clicked = true;
135                }
136            }
137                                                                                                   
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            }
148                                                                                                   
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            }
158                                                                                                   
159            function minMax(min, max)
160            {
161                if (min == null)
162                    var min = '';
163                if (max == null)
164                    var max = '';
165                                                                                                                                                                                                                                                                                                                               
166                var specs = document.getElementById("answerSpecifications");
167                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
168                var answerDiv = document.createElement("div");
169                                                                                                                                                                                                                                                                                                                                                                                                                                       
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' />";
173                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
174                specs.appendChild(answerDiv);
175            }     
176                                                                           
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            }
192                                                           
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 = '';
205                                                                                                                                                                                                                                                       
206                var specs = document.getElementById("answerSpecifications");
207                                                                                                                                                                                                                                                                                                                                                                                                                                               
208                var answerDiv = document.createElement("div");
209                answerDiv.className = "answerDiv";
210                                                                                                                                                                               
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";
217                                                                                                                                                                               
218                var leftInput = document.createElement("input");
219                leftInput.type = "text";
220                leftInput.value = left;
221                leftInput.name= "ans1";
222                leftInput.setAttribute("onchange", "handleAnswerChange()");
223                                                                                                                                                                               
224                var rightInput = document.createElement("input");
225                rightInput.type = "text";
226                rightInput.value = right;
227                rightInput.name = "ans2";
228                rightInput.setAttribute("onchange", "handleAnswerChange()");
229                                                                                                                                                                               
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";
237                                                                                                                                                                               
238                answerDiv.appendChild(leftLabel);
239                answerDiv.appendChild(leftInput);
240                answerDiv.appendChild(rightLabel);
241                answerDiv.appendChild(rightInput);
242                answerDiv.appendChild(scaleLabel);
243                answerDiv.appendChild(scaleInput);
244                                                                                                                                                                                                                                                                                                                                                                                                                           
245                specs.appendChild(answerDiv);
246            }   
247                                           
248            function newCategory()
249            {
250                var categoryBox = document.getElementById("categoryBox");
251                categoryBox.innerHTML = "";
252                                               
253                var categoryInput = document.createElement("input");
254                categoryInput.name = "questionCategory";
255                                               
256                categoryBox.appendChild(categoryInput);
257            }
258                                                       
259            function clearFields()
260            {
261                clearCategory();
262                clearCode();
263                clearTitle();
264                clearDescription();
265                clearType();
266            }
267                                           
268            function clearCategory()
269            {
270                var categoryBox = document.getElementById("categoryBox");
271                categoryBox.innerHTML = "";
272                                               
273                var questionCategorySelect = document.createElement("select");
274                questionCategorySelect.setAttribute("name", "questionCategory");
275                questionCategorySelect.id = "questionCategorySelect";
276                                               
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";
282                                               
283                categoryBox.appendChild(questionCategorySelect);
284                categoryBox.appendChild(newCategoryButton);
285            }
286                                           
287            function clearCode()
288            {
289                var codeInput = document.getElementById("questionCode");
290                codeInput.value = "";
291            }
292                                           
293            function clearTitle()
294            {
295                var titleInput = document.getElementById("questionTitle");
296                titleInput.value ="";
297            }
298                                           
299            function clearDescription()
300            {
301                var descriptionInput = document.getElementById("questionDescription");
302                descriptionInput.value = "";
303            }
304                                           
305            function clearType()
306            {
307                var typeSelect = document.getElementById("questionTypeSelect");
308                typeSelect.selectedIndex = 0;
309                clearSpecifications();
310            }
311                                           
312        </script>
313        <?php
314    }
315
316    private function displayList() {
317        ?>
318        <div id="questionListWrapper">
319            <select id="questionsList" size="9999">
320                <?php $this->populateList(); ?>
321            </select>
322        </div>
323        <?php
324    }
325
326    private function displayEditPanel() {
327        ?>
328        <div id="questionCreation" class="floatLeft">
329            <?php $this->displayForm(); ?>
330        </div>
331        <?php
332    }
333
334    private function displayForm() {
335        ?>
336        <form id="questionEditForm" method="post" action="" onsubmit="">
337            <table class="questionTable">
338                <tr>
339                    <td><label for="questionCategory">Category</label></td>
340                    <td id="categoryBox"><!-- Select should be filled with existing categories-->
341                        <?php $this->questionCategorySelect(); ?>
342                    </td>
343                </tr>
344                <tr>
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>
350                    <td><input id="questionTitle" name="questionTitle" size="60" /></td>
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">
359                        <select id="questionTypeSelect" name="questionType" onchange="handleType(this)">
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>
370            <input id="clearQuestionFields" type="button" onclick="clearFields()" class="surveyButton" value="Clear" />
371            <input id="saveQuestion" type="submit" class="surveyButton" value="Save" />
372        </form>
373        <?php
374    }
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    }
386
387    private function generateCategoryOptions() {
388        $categories = array();
389
390        foreach ($this->questions as $question) {
391            $category = $question->category;
392            array_push($categories, $category);
393        }
394        $categories = array_unique($categories);
395
396        // You might want to escape quotes and stuff here
397        foreach ($categories as $category) {
398            ?>
399            <option value="<?php echo $category; ?>"><?php echo $category; ?></option>
400            <?php
401        }
402    }
403
404    /**
405     * Populates the question list. Sorts the list first by question category.
406     */
407    private function populateList() {
408
409        $this->questions = $this->sortByCategory($this->questions);
410
411        $currentCategory = null;
412
413        foreach ($this->questions as $question) {
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            }
423            ?>
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
429                <?php
430            }
431            ?></optgroup><?php
432    }
433
434    /**
435     *
436     * @param type $questions
437     */
438    private function sortByCategory($questions) {
439        usort($questions, "cmp");
440        return $questions;
441    }
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}
458    ?>
Note: See TracBrowser for help on using the repository browser.