~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-06-13 12:51:29 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:767
Moved code to create user's jail version of conf.py from usrmgt server
    to makeuser.py, so it is performed during jail rebuilds as well as
    during initial creation, and refactored so it works during the rebuild.
    Now able to pull the svn password from the DB, set permissions, etc.
In short, Subversion now works in IVLE.
(And all you should have to do is run remakeallusers for it to work live on
the server).
Guys, I have to say this, I'm a bloody champ. :)

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
 
 
23
var server_key;
 
24
 
 
25
/* Begin religious debate (tabs vs spaces) here: */
 
26
/* (This string will be inserted in the console when the user presses the Tab
 
27
 * key) */
 
28
TAB_STRING = "    ";
 
29
 
 
30
/* Console DOM objects */
 
31
console_body = null;
 
32
console_filler = null;
 
33
 
 
34
windowpane_mode = false;
 
35
server_started = false;
 
36
 
 
37
interrupted = false;
 
38
 
 
39
/* Starts the console server, if it isn't already.
 
40
 * This can be called any number of times - it only starts the one server.
 
41
 * Note that this is asynchronous. It will return after signalling to start
 
42
 * the server, but there is no guarantee that it has been started yet.
 
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, and server_port.
 
47
 *
 
48
 * \param callback Function which will be called after the server has been
 
49
 * started. No parameters are passed. May be null.
 
50
 */
 
51
function start_server(callback)
 
52
{
 
53
    if (server_started)
 
54
    {
 
55
        callback();
 
56
        return;
 
57
    }
 
58
    var callback1 = function(xhr)
 
59
        {
 
60
            var json_text = xhr.responseText;
 
61
            server_key = JSON.parse(json_text);
 
62
            server_started = true;
 
63
            if (callback != null)
 
64
                callback();
 
65
        }
 
66
    ajax_call(callback1, "consoleservice", "start", {}, "POST");
 
67
}
 
68
 
 
69
/** Initialises the console. All apps which import console are required to
 
70
 * call this function.
 
71
 * Optional "windowpane" (bool), if true, will cause the console to go into
 
72
 * "window pane" mode which will allow it to be opened and closed, and float
 
73
 * over the page.
 
74
 * (Defaults to closed).
 
75
 */
 
76
function console_init(windowpane)
 
77
{
 
78
    /* Set up the console as a floating pane */
 
79
    console_body = document.getElementById("console_body");
 
80
    /* If there is no console body, don't worry.
 
81
     * (This lets us import console.js even on pages without a console box */
 
82
    if (console_body == null) return;
 
83
    console_filler = document.getElementById("console_filler");
 
84
    if (windowpane)
 
85
    {
 
86
        windowpane_mode = true;
 
87
        console_minimize();
 
88
    }
 
89
}
 
90
 
 
91
/** Hide the main console panel, so the console minimizes to just an input box
 
92
 *  at the page bottom. */
 
93
function console_minimize()
 
94
{
 
95
    if (!windowpane_mode) return;
 
96
    console_body.setAttribute("class", "windowpane minimal");
 
97
    console_filler.setAttribute("class", "windowpane minimal");
 
98
}
 
99
 
 
100
/** Show the main console panel, so it enlarges out to its full size.
 
101
 */
 
102
function console_maximize()
 
103
{
 
104
    if (!windowpane_mode) return;
 
105
    console_body.setAttribute("class", "windowpane maximal");
 
106
    console_filler.setAttribute("class", "windowpane maximal");
 
107
}
 
108
 
 
109
/* current_text is the string currently on the command line.
 
110
 * If non-empty, it will be stored at the bottom of the history.
 
111
 */
 
112
function historyUp(current_text)
 
113
{
 
114
    /* Remember the changes made to this item */
 
115
    this.edited[this.cursor] = current_text;
 
116
    if (this.cursor > 0)
 
117
    {
 
118
        this.cursor--;
 
119
    }
 
120
    this.earliestCursor = this.cursor;
 
121
}
 
122
 
 
123
function historyDown(current_text)
 
124
{
 
125
    /* Remember the changes made to this item */
 
126
    this.edited[this.cursor] = current_text;
 
127
    if (this.cursor < this.items.length - 1)
 
128
    {
 
129
        this.cursor++;
 
130
    }
 
131
}
 
132
 
 
133
function historyCurr()
 
134
{
 
135
    return this.edited[this.cursor];
 
136
}
 
137
 
 
138
function historySubmit(text)
 
139
{
 
140
    /* Copy the selected item's "edited" version over the permanent version of
 
141
     * the last item. */
 
142
    this.items[this.items.length-1] = text;
 
143
    /* Add a new blank item */
 
144
    this.items[this.items.length] = "";
 
145
    this.cursor = this.items.length-1;
 
146
    /* Blow away all the edited versions, replacing them with the existing
 
147
     * items set.
 
148
     * Not the whole history - just start from the earliest edited one.
 
149
     * (This avoids slowdown over extended usage time).
 
150
     */
 
151
    for (var i=this.earliestCursor; i<=this.cursor; i++)
 
152
        this.edited[i] = this.items[i];
 
153
    this.earliestCursor = this.cursor;
 
154
}
 
155
 
 
156
function historyShow()
 
157
{
 
158
    var res = "";
 
159
    for (var i = 0; i < this.items.length; i++)
 
160
    {
 
161
        if (i == this.cursor)
 
162
        {
 
163
            res += "["
 
164
        }
 
165
        res += this.items[i].toString();
 
166
        if (i == this.cursor)
 
167
        {
 
168
            res += "]"
 
169
        }
 
170
        res += " "
 
171
    }
 
172
    if (this.cursor == this.items.length)
 
173
    {
 
174
        res += "[]";
 
175
    }
 
176
    return res;
 
177
}
 
178
 
 
179
/* How history works
 
180
 * This is a fairly complex mechanism due to complications when editing
 
181
 * history items. We store two arrays. "items" is the permanent history of
 
182
 * each item. "edited" is a "volatile" version of items - the edits made to
 
183
 * the history between now and last time you hit "enter".
 
184
 * This is because the user can go back and edit any of the previous items,
 
185
 * and the edits are remembered until they hit enter.
 
186
 *
 
187
 * When hitting enter, the "edited" version of the currently selected item
 
188
 * replaces the "item" version of the last item in the list.
 
189
 * Then a new blank item is created, for the new line of input.
 
190
 * Lastly, all the "edited" versions are replaced with their stable versions.
 
191
 *
 
192
 * Cursor never points to an invalid location.
 
193
 */
 
194
function History()
 
195
{
 
196
    this.items = new Array("");
 
197
    this.edited = new Array("");
 
198
    this.cursor = 0;
 
199
    this.earliestCursor = 0;
 
200
    this.up = historyUp;
 
201
    this.down = historyDown;
 
202
    this.curr = historyCurr;
 
203
    this.submit = historySubmit;
 
204
    this.show = historyShow;
 
205
}
 
206
 
 
207
var hist = new History();
 
208
 
 
209
function set_interrupt()
 
210
{
 
211
    interrupted = true;
 
212
}
 
213
 
 
214
function clear_output()
 
215
{
 
216
    var output = document.getElementById("console_output");
 
217
    while (output.firstChild)
 
218
    {
 
219
        output.removeChild(output.firstChild);
 
220
    }
 
221
}
 
222
 
 
223
/** Send a line of text to the Python server, wait for its return, and react
 
224
 * to its response by writing to the output box.
 
225
 * Also maximize the console window if not already.
 
226
 */
 
227
function console_enter_line(inputbox, which)
 
228
{
 
229
    interrupted = false;
 
230
 
 
231
    if (typeof(inputbox) == "string")
 
232
    {
 
233
        var inputline = inputbox;
 
234
        inputbox = null;
 
235
        var graytimer = null;
 
236
    }
 
237
    else
 
238
    {
 
239
        GLOBAL_inputbox = inputbox;     /* For timer */
 
240
        var inputline = inputbox.value;
 
241
        var graytimer = setTimeout("GLOBAL_inputbox.setAttribute(\"class\", "
 
242
            + "\"disabled\");", 100);
 
243
    }
 
244
    var output = document.getElementById("console_output");
 
245
    {
 
246
        // Print ">>>" span
 
247
        var span = document.createElement("span");
 
248
        span.setAttribute("class", "inputPrompt");
 
249
        span.appendChild(document.createTextNode(">>> "));
 
250
        output.appendChild(span);
 
251
        // Print input line itself in a span
 
252
        var span = document.createElement("span");
 
253
        span.setAttribute("class", "inputMsg");
 
254
        span.appendChild(document.createTextNode(inputline + "\n"));
 
255
        output.appendChild(span);
 
256
    }
 
257
    var args = {"key": server_key, "text":inputline};
 
258
    var callback = function(xhr)
 
259
        {
 
260
            console_response(inputbox, graytimer, inputline, xhr.responseText);
 
261
        }
 
262
    /* Disable the text box */
 
263
    if (inputbox != null)
 
264
        inputbox.setAttribute("disabled", "disabled");
 
265
    ajax_call(callback, "consoleservice", which, args, "POST");
 
266
}
 
267
 
 
268
function console_response(inputbox, graytimer, inputline, responseText)
 
269
{
 
270
    try
 
271
    {
 
272
        var res = JSON.parse(responseText);
 
273
    }
 
274
    catch (e)
 
275
    {
 
276
        alert("An internal error occurred in the python console.");
 
277
        return;
 
278
    }
 
279
    var output = document.getElementById("console_output");
 
280
    if (res.hasOwnProperty('okay'))
 
281
    {
 
282
        // Success!
 
283
        if (res.okay)
 
284
        {
 
285
            output.appendChild(document.createTextNode(res.okay + "\n"));
 
286
            output.appendChild(span);
 
287
        }
 
288
        // set the prompt to >>>
 
289
        var prompt = document.getElementById("console_prompt");
 
290
        prompt.replaceChild(document.createTextNode(">>> "), prompt.firstChild);
 
291
    }
 
292
    else if (res.hasOwnProperty('exc'))
 
293
    {
 
294
        // Failure!
 
295
        // print out the error message (res.exc)
 
296
        var span = document.createElement("span");
 
297
        span.setAttribute("class", "errorMsg");
 
298
        span.appendChild(document.createTextNode(res.exc + "\n"));
 
299
        output.appendChild(span);
 
300
        // set the prompt to >>>
 
301
        var prompt = document.getElementById("console_prompt");
 
302
        prompt.replaceChild(document.createTextNode(">>> "), prompt.firstChild);
 
303
    }
 
304
    else if (res.hasOwnProperty('restart') && res.hasOwnProperty('key'))
 
305
    {
 
306
        // Server has indicated that the console should be restarted
 
307
        
 
308
        // Get the new key (host, port, magic)
 
309
        server_key = res.key;
 
310
 
 
311
        // Print a reason to explain why we'd do such a horrible thing
 
312
        // (console timeout, server error etc.)
 
313
        var span = document.createElement("span");
 
314
        span.setAttribute("class", "errorMsg");
 
315
        span.appendChild(document.createTextNode("Console Restart: " + res.restart + "\n"));
 
316
        output.appendChild(span);
 
317
        // set the prompt to >>>
 
318
        var prompt = document.getElementById("console_prompt");
 
319
        prompt.replaceChild(document.createTextNode(">>> "), prompt.firstChild);
 
320
 
 
321
    }
 
322
    else if (res.hasOwnProperty('more'))
 
323
    {
 
324
        // Need more input, so set the prompt to ...
 
325
        var prompt = document.getElementById("console_prompt");
 
326
        prompt.replaceChild(document.createTextNode("... "), prompt.firstChild);
 
327
    }
 
328
    else if (res.hasOwnProperty('output'))
 
329
    {
 
330
        if (res.output.length > 0)
 
331
        {
 
332
            output.appendChild(document.createTextNode(res.output));
 
333
        }
 
334
        var callback = function(xhr)
 
335
            {
 
336
                console_response(inputbox, graytimer,
 
337
                                 null, xhr.responseText);
 
338
            }
 
339
        if (interrupted)
 
340
        {
 
341
            var kind = "interrupt";
 
342
        }
 
343
        else
 
344
        {
 
345
            var kind = "chat";
 
346
        }
 
347
        var args = {"key": server_key, "text":''};
 
348
        ajax_call(callback, "consoleservice", kind, args, "POST");
 
349
 
 
350
        // Open up the console so we can see the output
 
351
        // FIXME: do we need to maximize here?
 
352
        console_maximize();
 
353
 
 
354
        /* Auto-scrolling */
 
355
        divScroll.activeScroll();
 
356
 
 
357
        // Return early, so we don't re-enable the input box.
 
358
        return;
 
359
    }
 
360
    else {
 
361
        // assert res.hasOwnProperty('input')
 
362
        var prompt = document.getElementById("console_prompt");
 
363
        prompt.replaceChild(document.createTextNode("+++ "), prompt.firstChild);
 
364
    }
 
365
 
 
366
    if (inputbox != null)
 
367
    {
 
368
        /* Re-enable the text box */
 
369
        clearTimeout(graytimer);
 
370
        inputbox.removeAttribute("disabled");
 
371
        inputbox.removeAttribute("class");
 
372
        interrupted = false;
 
373
    }
 
374
 
 
375
    /* Open up the console so we can see the output */
 
376
    console_maximize();
 
377
    /* Auto-scrolling */
 
378
    divScroll.activeScroll();
 
379
 
 
380
    // Focus the input box by default
 
381
    document.getElementById("console_output").focus()
 
382
    document.getElementById("console_inputText").focus()
 
383
}
 
384
 
 
385
function catch_input(key)
 
386
{
 
387
    var inp = document.getElementById('console_inputText');
 
388
    switch (key)
 
389
    {
 
390
    case 9:                 /* Tab key */
 
391
        var selstart = inp.selectionStart;
 
392
        var selend = inp.selectionEnd;
 
393
        if (selstart == selend)
 
394
        {
 
395
            /* No selection, just a carat. Insert a tab here. */
 
396
            inp.value = inp.value.substr(0, selstart)
 
397
                + TAB_STRING + inp.value.substr(selstart);
 
398
        }
 
399
        else
 
400
        {
 
401
            /* Text is selected. Just indent the whole line
 
402
             * by inserting a tab at the start */
 
403
            inp.value = TAB_STRING + inp.value;
 
404
        }
 
405
        /* Update the selection so the same characters as before are selected
 
406
         */
 
407
        inp.selectionStart = selstart + TAB_STRING.length;
 
408
        inp.selectionEnd = inp.selectionStart + (selend - selstart);
 
409
        /* Cancel the event, so the TAB key doesn't move focus away from this
 
410
         * box */
 
411
        return false;
 
412
        /* Note: If it happens that some browsers don't support event
 
413
         * cancelling properly, this hack might work instead:
 
414
        setTimeout(
 
415
            "document.getElementById('console_inputText').focus()",
 
416
            0);
 
417
         */
 
418
        break;
 
419
    case 13:                /* Enter key */
 
420
        var callback = function()
 
421
        {
 
422
            /* Send the line of text to the server */
 
423
            console_enter_line(inp, "chat");
 
424
            hist.submit(inp.value);
 
425
            inp.value = hist.curr();
 
426
        }
 
427
        /* Start the server if it hasn't already been started */
 
428
        start_server(callback);
 
429
        break;
 
430
    case 38:                /* Up arrow */
 
431
        hist.up(inp.value);
 
432
        inp.value = hist.curr();
 
433
        break;
 
434
    case 40:                /* Down arrow */
 
435
        hist.down(inp.value);
 
436
        inp.value = hist.curr();
 
437
        break;
 
438
    }
 
439
}
 
440
 
 
441
/**** Following Code modified from ******************************************/
 
442
/**** http://radio.javaranch.com/pascarello/2006/08/17/1155837038219.html ***/
 
443
/****************************************************************************/
 
444
var chatscroll = new Object();
 
445
 
 
446
chatscroll.Pane = function(scrollContainerId)
 
447
{
 
448
    this.scrollContainerId = scrollContainerId;
 
449
}
 
450
 
 
451
chatscroll.Pane.prototype.activeScroll = function()
 
452
{
 
453
    var scrollDiv = document.getElementById(this.scrollContainerId);
 
454
    var currentHeight = 0;
 
455
        
 
456
    if (scrollDiv.scrollHeight > 0)
 
457
        currentHeight = scrollDiv.scrollHeight;
 
458
    else 
 
459
        if (objDiv.offsetHeight > 0)
 
460
            currentHeight = scrollDiv.offsetHeight;
 
461
 
 
462
    scrollDiv.scrollTop = currentHeight;
 
463
 
 
464
    scrollDiv = null;
 
465
}
 
466
 
 
467
var divScroll = new chatscroll.Pane('console_output');