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

« back to all changes in this revision

Viewing changes to www/media/console/console.js

  • Committer: mattgiuca
  • Date: 2008-02-05 01:41:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:409
Moved www/conf and www/common to a new directory lib. This separates the "web"
part of IVLE from what is becoming less web oriented (at least from Apache's
standpoint).
Modified setup.py to install this lib directory correctly and write conf in
the right place. Also adds the lib directory to ivle.pth.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: Console (Client-side JavaScript)
 
19
 * Author: Tom Conway, Matt Giuca
 
20
 * Date: 30/1/2008
 
21
 */
 
22
 
1
23
digest_constant = "hello";
2
24
 
3
25
var server_host;
4
26
var server_port;
5
27
var server_magic;
6
28
 
7
 
/* Starts the console server.
8
 
 * Returns an object with fields "host", "port", "magic" describing the
9
 
 * server.
 
29
/* Begin religious debate (tabs vs spaces) here: */
 
30
/* (This string will be inserted in the console when the user presses the Tab
 
31
 * key) */
 
32
TAB_STRING = "    ";
 
33
 
 
34
/* Console DOM objects */
 
35
console_body = null;
 
36
console_filler = null;
 
37
 
 
38
windowpane_mode = false;
 
39
server_started = false;
 
40
 
 
41
/* Starts the console server, if it isn't already.
 
42
 * This can be called any number of times - it only starts the one server.
 
43
 * This is a separate step from console_init, as the server is only to be
 
44
 * started once the first command is entered.
 
45
 * Does not return a value. Writes to global variables
 
46
 * server_host, server_port, server_magic.
10
47
 */
11
48
function start_server()
12
49
{
 
50
    if (server_started) return;
13
51
    var xhr = ajax_call("consoleservice", "start", {}, "POST");
14
52
    var json_text = xhr.responseText;
15
 
    return JSON.parse(json_text);
16
 
}
17
 
 
18
 
function onload()
19
 
{
20
 
    /* Start the server */
21
 
    var server_info = start_server();
 
53
    var server_info = JSON.parse(json_text);
22
54
    server_host = server_info.host;
23
55
    server_port = server_info.port;
24
56
    server_magic = server_info.magic;
25
 
}
26
 
 
27
 
/* Below here imported from trunk/console/console.js
28
 
 * (Tom Conway)
29
 
 */
30
 
 
31
 
var magic = 'xyzzy';
32
 
 
33
 
function historyUp()
34
 
{
35
 
    if (this.cursor >= 0)
 
57
    server_started = true;
 
58
}
 
59
 
 
60
/** Initialises the console. All apps which import console are required to
 
61
 * call this function.
 
62
 * Optional "windowpane" (bool), if true, will cause the console to go into
 
63
 * "window pane" mode which will allow it to be opened and closed, and float
 
64
 * over the page.
 
65
 * (Defaults to closed).
 
66
 */
 
67
function console_init(windowpane)
 
68
{
 
69
    /* Set up the console as a floating pane */
 
70
    console_body = document.getElementById("console_body");
 
71
    /* If there is no console body, don't worry.
 
72
     * (This lets us import console.js even on pages without a console box */
 
73
    if (console_body == null) return;
 
74
    console_filler = document.getElementById("console_filler");
 
75
    if (windowpane)
 
76
    {
 
77
        windowpane_mode = true;
 
78
        console_minimize();
 
79
    }
 
80
    /* TEMP: Start the server now.
 
81
     * Ultimately we want the server to start only when a line is typed, but
 
82
     * it currently does it asynchronously and doesn't start in time for the
 
83
     * first line. */
 
84
    start_server();
 
85
}
 
86
 
 
87
/** Hide the main console panel, so the console minimizes to just an input box
 
88
 *  at the page bottom. */
 
89
function console_minimize()
 
90
{
 
91
    if (!windowpane_mode) return;
 
92
    console_body.setAttribute("class", "windowpane minimal");
 
93
    console_filler.setAttribute("class", "windowpane minimal");
 
94
}
 
95
 
 
96
/** Show the main console panel, so it enlarges out to its full size.
 
97
 */
 
98
function console_maximize()
 
99
{
 
100
    if (!windowpane_mode) return;
 
101
    console_body.setAttribute("class", "windowpane maximal");
 
102
    console_filler.setAttribute("class", "windowpane maximal");
 
103
    /* Focus the input box by default */
 
104
    document.getElementById("console_inputText").focus()
 
105
}
 
106
 
 
107
/* current_text is the string currently on the command line.
 
108
 * If non-empty, it will be stored at the bottom of the history.
 
109
 */
 
110
function historyUp(current_text)
 
111
{
 
112
    /* Remember the changes made to this item */
 
113
    this.edited[this.cursor] = current_text;
 
114
    if (this.cursor > 0)
36
115
    {
37
116
        this.cursor--;
38
117
    }
 
118
    this.earliestCursor = this.cursor;
39
119
}
40
120
 
41
 
function historyDown()
 
121
function historyDown(current_text)
42
122
{
43
 
    if (this.cursor < this.items.length)
 
123
    /* Remember the changes made to this item */
 
124
    this.edited[this.cursor] = current_text;
 
125
    if (this.cursor < this.items.length - 1)
44
126
    {
45
127
        this.cursor++;
46
128
    }
48
130
 
49
131
function historyCurr()
50
132
{
51
 
    if (this.cursor < 0 || this.cursor >= this.items.length)
52
 
    {
53
 
        return "";
54
 
    }
55
 
    return this.items[this.cursor];
 
133
    return this.edited[this.cursor];
56
134
}
57
135
 
58
 
function historyAdd(text)
 
136
function historySubmit(text)
59
137
{
60
 
    this.items[this.items.length] = text;
61
 
    this.cursor = this.items.length;
 
138
    /* Copy the selected item's "edited" version over the permanent version of
 
139
     * the last item. */
 
140
    this.items[this.items.length-1] = text;
 
141
    /* Add a new blank item */
 
142
    this.items[this.items.length] = "";
 
143
    this.cursor = this.items.length-1;
 
144
    /* Blow away all the edited versions, replacing them with the existing
 
145
     * items set.
 
146
     * Not the whole history - just start from the earliest edited one.
 
147
     * (This avoids slowdown over extended usage time).
 
148
     */
 
149
    for (var i=this.earliestCursor; i<=this.cursor; i++)
 
150
        this.edited[i] = this.items[i];
 
151
    this.earliestCursor = this.cursor;
62
152
}
63
153
 
64
154
function historyShow()
65
155
{
66
156
    var res = "";
67
 
    if (this.cursor == -1)
68
 
    {
69
 
        res += "[]";
70
 
    }
71
157
    for (var i = 0; i < this.items.length; i++)
72
158
    {
73
159
        if (i == this.cursor)
88
174
    return res;
89
175
}
90
176
 
 
177
/* How history works
 
178
 * This is a fairly complex mechanism due to complications when editing
 
179
 * history items. We store two arrays. "items" is the permanent history of
 
180
 * each item. "edited" is a "volatile" version of items - the edits made to
 
181
 * the history between now and last time you hit "enter".
 
182
 * This is because the user can go back and edit any of the previous items,
 
183
 * and the edits are remembered until they hit enter.
 
184
 *
 
185
 * When hitting enter, the "edited" version of the currently selected item
 
186
 * replaces the "item" version of the last item in the list.
 
187
 * Then a new blank item is created, for the new line of input.
 
188
 * Lastly, all the "edited" versions are replaced with their stable versions.
 
189
 *
 
190
 * Cursor never points to an invalid location.
 
191
 */
91
192
function History()
92
193
{
93
 
    this.items = new Array();
94
 
    this.cursor = -1;
 
194
    this.items = new Array("");
 
195
    this.edited = new Array("");
 
196
    this.cursor = 0;
 
197
    this.earliestCursor = 0;
95
198
    this.up = historyUp;
96
199
    this.down = historyDown;
97
200
    this.curr = historyCurr;
98
 
    this.add = historyAdd;
 
201
    this.submit = historySubmit;
99
202
    this.show = historyShow;
100
203
}
101
204
 
102
205
var hist = new History();
103
206
 
104
 
function enter_line()
 
207
/** Send a line of text to the Python server, wait for its return, and react
 
208
 * to its response by writing to the output box.
 
209
 * Also maximize the console window if not already.
 
210
 */
 
211
function console_enter_line(inputline, which)
105
212
{
106
 
    var inp = document.getElementById('inputText');
107
 
    var digest = hex_md5(inp.value + magic);
 
213
    /* Start the server if it hasn't already been started */
 
214
    start_server();
 
215
    var digest = hex_md5(inputline + server_magic);
108
216
    var args = {"host": server_host, "port": server_port,
109
 
                    "digest":digest, "text":inp.value};
110
 
    var xmlhttp = ajax_call("consoleservice", "chat", args, "POST");
 
217
                    "digest":digest, "text":inputline};
 
218
    var xmlhttp = ajax_call("consoleservice", which, args, "POST");
111
219
 
112
220
    var res = JSON.parse(xmlhttp.responseText);
113
 
    var output = document.getElementById("output");
 
221
    var output = document.getElementById("console_output");
114
222
    {
115
223
        var pre = document.createElement("pre");
116
224
        pre.setAttribute("class", "inputMsg");
117
 
        pre.appendChild(document.createTextNode(inp.value + "\n"));
 
225
        pre.appendChild(document.createTextNode(inputline + "\n"));
118
226
        output.appendChild(pre);
119
227
    }
120
228
    if (res.hasOwnProperty('okay'))
134
242
            output.appendChild(pre);
135
243
        }
136
244
        // set the prompt to >>>
137
 
        var prompt = document.getElementById("prompt");
 
245
        var prompt = document.getElementById("console_prompt");
138
246
        prompt.replaceChild(document.createTextNode(">>> "), prompt.firstChild);
139
247
    }
140
248
    else if (res.hasOwnProperty('exc'))
141
249
    {
142
250
        // Failure!
 
251
        // print out any output that came before the error
 
252
        if (res.exc[0].length > 0)
 
253
        {
 
254
            var pre = document.createElement("pre");
 
255
            pre.setAttribute("class", "outputMsg");
 
256
            pre.appendChild(document.createTextNode(res.exc[0]));
 
257
            output.appendChild(pre);
 
258
        }
 
259
 
143
260
        // print out the error message (res.exc)
144
261
        var pre = document.createElement("pre");
145
262
        pre.setAttribute("class", "errorMsg");
146
 
        pre.appendChild(document.createTextNode(res.exc));
 
263
        pre.appendChild(document.createTextNode(res.exc[1]));
147
264
        output.appendChild(pre);
148
265
    }
149
266
    else if (res.hasOwnProperty('more'))
150
267
    {
151
268
        // Need more input, so set the prompt to ...
152
 
        var prompt = document.getElementById("prompt");
 
269
        var prompt = document.getElementById("console_prompt");
153
270
        prompt.replaceChild(document.createTextNode("... "), prompt.firstChild);
154
271
    }
155
272
    else {
156
273
        // assert res.hasOwnProperty('input')
157
 
        var prompt = document.getElementById("prompt");
 
274
        var prompt = document.getElementById("console_prompt");
158
275
        prompt.replaceChild(document.createTextNode("+++ "), prompt.firstChild);
159
276
    }
 
277
    /* Open up the console so we can see the output */
 
278
    console_maximize();
160
279
}
161
280
 
162
281
function catch_input(key)
163
282
{
164
 
    var inp = document.getElementById('inputText');
165
 
    if (key == 13)
166
 
    {
167
 
        enter_line();
168
 
        hist.add(inp.value);
169
 
        inp.value = hist.curr();
170
 
    }
171
 
    if (key == 38)
172
 
    {
173
 
        hist.up();
174
 
        inp.value = hist.curr();
175
 
    }
176
 
    if (key == 40)
177
 
    {
178
 
        hist.down();
179
 
        inp.value = hist.curr();
 
283
    var inp = document.getElementById('console_inputText');
 
284
    switch (key)
 
285
    {
 
286
    case 9:                 /* Tab key */
 
287
        var selstart = inp.selectionStart;
 
288
        var selend = inp.selectionEnd;
 
289
        if (selstart == selend)
 
290
        {
 
291
            /* No selection, just a carat. Insert a tab here. */
 
292
            inp.value = inp.value.substr(0, selstart)
 
293
                + TAB_STRING + inp.value.substr(selstart);
 
294
        }
 
295
        else
 
296
        {
 
297
            /* Text is selected. Just indent the whole line
 
298
             * by inserting a tab at the start */
 
299
            inp.value = TAB_STRING + inp.value;
 
300
        }
 
301
        /* Update the selection so the same characters as before are selected
 
302
         */
 
303
        inp.selectionStart = selstart + TAB_STRING.length;
 
304
        inp.selectionEnd = inp.selectionStart + (selend - selstart);
 
305
        /* Cancel the event, so the TAB key doesn't move focus away from this
 
306
         * box */
 
307
        return false;
 
308
        /* Note: If it happens that some browsers don't support event
 
309
         * cancelling properly, this hack might work instead:
 
310
        setTimeout(
 
311
            "document.getElementById('console_inputText').focus()",
 
312
            0);
 
313
         */
 
314
        break;
 
315
    case 13:                /* Enter key */
 
316
        /* Send the line of text to the server */
 
317
        console_enter_line(inp.value, "chat");
 
318
        hist.submit(inp.value);
 
319
        inp.value = hist.curr();
 
320
        break;
 
321
    case 38:                /* Up arrow */
 
322
        hist.up(inp.value);
 
323
        inp.value = hist.curr();
 
324
        break;
 
325
    case 40:                /* Down arrow */
 
326
        hist.down(inp.value);
 
327
        inp.value = hist.curr();
 
328
        break;
180
329
    }
181
330
}