~azzar1/unity/add-show-desktop-key

307 by mattgiuca
tutorial: Now each problem div has an ID. Added submit buttons which call
1
/* IVLE - Informatics Virtual Learning Environment
2
 * Copyright (C) 2007-2008 The University of Melbourne
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
 *
18
 * Module: Tutorial system (client)
19
 * Author: Matt Giuca
20
 * Date: 25/1/2008
21
 */
22
331 by mattgiuca
Console: Configured console to display properly as a "floating" window in the
23
/* Runs at startup. */
24
function onload()
25
{
26
    /* Set up the console plugin to display as a popup window */
27
    console_init(true);
28
}
29
325 by mattgiuca
tutorial: Added "run" button which submits the students code to the
30
/** User clicks "Run" button. Do an Ajax call and print the test output.
31
 */
32
function runproblem(problemid, filename)
33
{
34
    /* Get the source code the student is submitting */
35
    var problemdiv = document.getElementById(problemid);
36
    var problembox = problemdiv.getElementsByTagName("textarea")[0];
37
    var code = problembox.value;
38
333 by mattgiuca
console.js: enter_line now accepts the line as an argument instead of reading
39
    /* Dump the entire file to the console */
40
    /* FIXME: Multiple lines aren't received properly by the server */
41
    console_enter_line(code);
42
    return;
43
44
    /* TEMP: Old code here */
325 by mattgiuca
tutorial: Added "run" button which submits the students code to the
45
    var args = {"code": code, "problem": filename, "action": "run"};
46
47
    /* Send the form as multipart/form-data, since we are sending a whole lump
48
     * of Python code, it should be treated like a file upload. */
49
    var xhr = ajax_call("tutorialservice", "", args, "POST",
50
        "multipart/form-data");
51
    var testresponse = JSON.parse(xhr.responseText);
52
    handle_runresponse(problemdiv, testresponse);
53
}
54
55
/** Given a response object (JSON-parsed object), displays the result of the
56
 * test to the user. This modifies the given problemdiv's children.
57
 */
58
function handle_runresponse(problemdiv, runresponse)
59
{
60
    var runoutput = problemdiv.getElementsByTagName("textarea")[1];
61
    dom_removechildren(runoutput);
62
    runoutput.appendChild(document.createTextNode(runresponse.stdout));
63
}
64
307 by mattgiuca
tutorial: Now each problem div has an ID. Added submit buttons which call
65
/** User clicks "Submit" button. Do an Ajax call and run the test.
66
 * problemid: "id" of the problem's div element.
67
 * filename: Filename of the problem's XML file (used to identify the problem
68
 *     when interacting with the server).
69
 */
70
function submitproblem(problemid, filename)
71
{
72
    /* Get the source code the student is submitting */
312 by mattgiuca
Full client-side testing - functional.
73
    var problemdiv = document.getElementById(problemid);
74
    var problembox = problemdiv.getElementsByTagName("textarea")[0];
75
    var code = problembox.value;
76
77
    var args = {"code": code, "problem": filename, "action": "test"};
78
79
    /* Send the form as multipart/form-data, since we are sending a whole lump
80
     * of Python code, it should be treated like a file upload. */
81
    var xhr = ajax_call("tutorialservice", "", args, "POST",
82
        "multipart/form-data");
83
    var testresponse = JSON.parse(xhr.responseText);
84
    handle_testresponse(problemdiv, testresponse);
85
}
86
87
/** Given a problem div, return the testoutput div which is its child.
88
 * (The div which is its child whose class is "testoutput".
89
 */
90
function get_testoutput(problemdiv)
91
{
92
    var childs = problemdiv.childNodes;
93
    var i;
94
    var testoutput;
95
    for (i=0; i<childs.length; i++)
96
        if (childs[i].nodeType == problemdiv.ELEMENT_NODE &&
97
            childs[i].getAttribute("class") == "testoutput")
98
            return childs[i];
99
    return null;
100
}
101
102
/** Given a response object (JSON-parsed object), displays the result of the
103
 * test to the user. This modifies the given problemdiv's children.
104
 */
105
function handle_testresponse(problemdiv, testresponse)
106
{
107
    var testoutput = get_testoutput(problemdiv);
108
    var i, j;
109
    var ul;
110
    var case_ul;
111
    if (testoutput == null) return;     /* should not happen */
112
    dom_removechildren(testoutput);
113
114
    ul = document.createElement("ul");
115
    testoutput.appendChild(ul);
116
117
    if ("critical_error" in testresponse)
118
    {
119
        /* Only one error - and it's bad.
120
         * Just print and stop */
121
        ul.appendChild(create_response_item("critical",
122
            testresponse.critical_error.name,
123
            testresponse.critical_error.detail));
124
        return;
125
    }
126
127
    for (i=0; i<testresponse.cases.length; i++)
128
    {
129
        var testcase = testresponse.cases[i];
130
        if ("exception" in testcase)
131
        {
132
            /* User's code threw an exception */
133
            fail_li = create_response_item("fail", testcase.name);
134
            ul.appendChild(fail_li);
135
            /* Create a sub-ul to display the failing cases. */
136
            case_ul = document.createElement("ul");
137
            fail_li.appendChild(case_ul);
138
            case_ul.appendChild(create_response_item("exception",
139
                testcase.exception.name, testcase.exception.detail));
140
        }
141
        else if (testcase.passed)
142
        {
143
            /* All parts of the test case passed. Just report the overall case
144
             * passing. */
145
            ul.appendChild(create_response_item("pass", testcase.name));
146
        }
147
        else
148
        {
149
            var fail_li = create_response_item("fail", testcase.name);
150
            ul.appendChild(fail_li);
151
            /* Create a sub-ul to display the failing cases. */
152
            case_ul = document.createElement("ul");
153
            fail_li.appendChild(case_ul);
154
            
155
            for (j=0; j<testcase.parts.length; j++)
156
            {
157
                var part = testcase.parts[j];
158
                if (part.passed)
159
                {
160
                    case_ul.appendChild(create_response_item("pass",
161
                        part.description));
162
                }
163
                else
164
                {
165
                    case_ul.appendChild(create_response_item("fail",
166
                        part.description, part.error_message));
167
                }
168
            }
169
        }
170
    }
171
}
172
173
/* DOM creators for test case response elements */
174
175
/** Create a <li> element for the result of a test case.
176
 * type: "pass", "fail", "exception" or "critical"
177
 * detail should be null for passing cases.
178
 * For exceptions and crits, "desc" is the exception name,
179
 * detail is the message.
180
 */
181
function create_response_item(type, desc, detail)
182
{
183
    var crit = false;
184
    if (type == "critical")
185
    {
186
        /* Crits look like exceptions, but are slightly different */
187
        crit = true;
188
        type = "exception";
189
    }
190
    var li = document.createElement("li");
191
    li.setAttribute("class", type);
192
    var b = document.createElement("b");
193
    var text = type[0].toUpperCase() + type.substr(1) + ":";
194
    b.appendChild(document.createTextNode(text));
195
    li.appendChild(b);
196
    if (type == "pass")
197
        text = desc;
198
    else if (type == "fail")
199
        text = desc + (detail == null ? "" : ":");
200
    else if (type == "exception")
201
    {
202
        if (crit)
203
            text = "Your code could not be executed, "
204
                + "due to the following error:";
205
        else
206
            text = "The following exception occured "
207
                + "while running your code:";
208
    }
209
    li.appendChild(document.createTextNode(" " + text));
210
    if (type == "pass" || (type == "fail" && detail == null))
211
        return li;
212
213
    /* Non-passes, display the error message */
214
    li.appendChild(document.createElement("br"));
215
    if (type == "exception")
216
    {
217
        b = document.createElement("b");
218
        b.appendChild(document.createTextNode(desc + ":"));
219
        li.appendChild(b);
220
    }
221
    li.appendChild(document.createTextNode(detail));
222
    return li;
307 by mattgiuca
tutorial: Now each problem div has an ID. Added submit buttons which call
223
}