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

170 by mattgiuca
browser: Added CSS and JS files (not much in them).
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: File Browser (client)
19
 * Author: Matt Giuca
20
 * Date: 11/1/2008
21
 */
22
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
23
/* Url names for apps */
1339 by William Grant
Revert client-side parts of r1333; reliance on the deprecated tab mechanism is to be avoided.
24
this_app = "files";
208 by mattgiuca
dispatch.html, ivle.css: "apptabs" is now an ID, not a class.
25
edit_app = "edit";
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
26
service_app = "fileservice";
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
27
serve_app = "serve";
28
download_app = "download";
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
29
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
30
/* Mapping MIME types onto handlers.
31
 * "text" : When navigating to a text file, the text editor is opened.
32
 * "image" : When navigating to an image, the image is displayed (rather than
33
 *              going to the text editor).
34
 * "audio" : When navigating to an audio file, a "play" button is presented.
35
 * "binary" : When navigating to a binary file, offer it as a download through
36
 *              "serve".
37
 *
38
 * If a file is not on the list, its default action is determined by the first
39
 * part of its content type, where "text/*", "image/*" and "audio/*" are
40
 * treated as above, and other types are simply treated as binary.
41
 */
42
type_handlers = {
43
    "application/x-javascript" : "text",
44
    "application/javascript" : "text",
45
    "application/json" : "text",
489 by agdimech
browser.js, editor.js: Fixed the syntax error which was resulting due to a trailing comma.
46
    "application/xml" : "text"
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
47
};
48
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
49
/* Mapping MIME types to icons, just the file's basename */
50
type_icons = {
51
    "text/directory": "dir.png",
489 by agdimech
browser.js, editor.js: Fixed the syntax error which was resulting due to a trailing comma.
52
    "text/x-python": "py.png"
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
53
};
54
55
default_type_icon = "txt.png";
56
57
/* Relative to IVLE root */
1099.1.68 by William Grant
Move the remaining images to the new framework, in the new ivle.webapp.core
58
type_icons_path = "+media/ivle.webapp.core/images/mime";
59
type_icons_path_large = "+media/ivle.webapp.core/images/mime/large";
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
60
61
/* Mapping SVN status to icons, just the file's basename */
62
svn_icons = {
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
63
    "unversioned": null,
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
64
    "normal": "normal.png",
213 by mattgiuca
Fileservice / Files (Python and JS files):
65
    "added": "added.png",
66
    "missing": "missing.png",
67
    "deleted": "deleted.png",
578 by dcoles
fileservice: Added code to allow browing of past revisons in the File Browser
68
    "modified": "modified.png",
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
69
    "conflicted": "conflicted.png",
578 by dcoles
fileservice: Added code to allow browing of past revisons in the File Browser
70
    "revision": "revision.png"
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
71
};
72
213 by mattgiuca
Fileservice / Files (Python and JS files):
73
/* Mapping SVN status to "nice" strings */
74
svn_nice = {
75
    "unversioned": "Temporary file",
76
    "normal": "Permanent file",
77
    "added": "Temporary file (scheduled to be added)",
78
    "missing": "Permanent file (missing)",
79
    "deleted": "Permanent file (scheduled for deletion)",
80
    "replaced": "Permanent file (replaced)",
81
    "modified": "Permanent file (modified)",
82
    "merged": "Permanent file (merged)",
578 by dcoles
fileservice: Added code to allow browing of past revisons in the File Browser
83
    "conflicted": "Permanent file (conflicted)",
84
    "revision": "Past Permanent file (revision)"
213 by mattgiuca
Fileservice / Files (Python and JS files):
85
};
86
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
87
default_svn_icon = null;
213 by mattgiuca
Fileservice / Files (Python and JS files):
88
default_svn_nice = "Unknown status";
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
89
1099.1.68 by William Grant
Move the remaining images to the new framework, in the new ivle.webapp.core
90
svn_icons_path = "+media/ivle.webapp.core/images/svn";
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
91
1099.1.68 by William Grant
Move the remaining images to the new framework, in the new ivle.webapp.core
92
published_icon = "+media/ivle.webapp.core/images/interface/published.png";
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
93
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
94
/* List of MIME types considered "executable" by the system.
95
 * Executable files offer a "run" link, implying that the "serve"
96
 * application can interpret them.
97
 */
98
types_exec = [
489 by agdimech
browser.js, editor.js: Fixed the syntax error which was resulting due to a trailing comma.
99
    "text/x-python"
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
100
];
101
211 by mattgiuca
fileservice/listing: Slight change to date format.
102
103
/* Global variables */
104
602 by mattgiuca
util.js: Added shallow_copy_object function.
105
/** The listing object returned by the server as JSON */
106
file_listing = null;
107
current_file = null;
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
108
current_revision = null;
211 by mattgiuca
fileservice/listing: Slight change to date format.
109
current_path = "";
110
597 by mattgiuca
Major refactor of actions in File browser.
111
/** Filenames of all files selected
112
 * (Only used by dir listings, but still needs to be [] for files, so that
113
 * update_actions knows that nothing is selected).
114
 */
115
selected_files = [];
116
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
117
upload_callback_count = 0;      /* See upload_callback */
118
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
119
/** Calls the server using Ajax, performing an action on the server side.
120
 * Receives the response from the server and performs a refresh of the page
121
 * contents, updating it to display the returned data (such as a directory
122
 * listing, file preview, or editor pane).
123
 * Always makes a POST request.
124
 * No return value.
125
 *
126
 * \param action String. Name of the action to perform, as defined in the
127
 *     fileservice API.
128
 * \param path URL path to make the request to, within the application.
129
 * \param args Argument object, as described in util.parse_url and friends.
130
 *      This should contain the arguments to the action, but NOT the action
131
 *      itself. (Also a minor side-effect; the "args" object will be mutated
132
 *      to include the action attribute).
133
 * \param content_type String, optional.
134
 *      May be "application/x-www-form-urlencoded" or "multipart/form-data".
135
 *      Defaults to "application/x-www-form-urlencoded".
136
 *      "multipart/form-data" is recommended for large uploads.
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
137
 * \param callback, optional.
138
 *      A callback function for after the action has been handled.
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
139
 */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
140
function do_action(action, path, args, content_type, callback)
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
141
{
142
    args.action = action;
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
143
    /* Callback action, when the server returns */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
144
    var callback_inner = function(response)
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
145
        {
146
            /* Check for action errors reported by the server, and report them
147
             * to the user */
148
            var error = response.getResponseHeader("X-IVLE-Action-Error");
1169 by William Grant
Don't treat an empty X-IVLE-Action-Error header as an error condition.
149
            if (error != null && error != "")
785 by mattgiuca
fileservice_lib/__init__.py: X-IVLE-Action-Error HTTP response header is now
150
                /* Note: This header (in particular) comes URI-encoded, to
151
                 * allow multi-line error messages. Decode */
152
                alert("Error: " + decodeURIComponent(error.toString()) + ".");
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
153
            /* Now read the response and set up the page accordingly */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
154
            if (callback != null)
155
                callback(path, response);
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
156
        }
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
157
    /* Call the server and perform the action. This mutates the server. */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
158
    ajax_call(callback_inner, service_app, path, args, "POST", content_type);
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
159
}
160
161
/** Calls the server using Ajax, requesting a directory listing. This should
162
 * not modify the server in any way. Receives the response from the server and
163
 * performs a refresh of the page contents, updating it to display the
164
 * returned data (such as a directory listing, file preview, or editor pane).
165
 * Called "navigate", can also be used for a simple refresh.
166
 * Always makes a GET request.
167
 * No return value.
168
 */
603 by mattgiuca
Console now starts up in the user's home directory.
169
function navigate(path)
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
170
{
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
171
    callback = function(response)
172
        {
173
            /* Read the response and set up the page accordingly */
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
174
            handle_response(path, response, false, url.args);
559 by mattgiuca
Major JavaScript refactor: util.ajax_call is now asynchronous, not
175
        }
578 by dcoles
fileservice: Added code to allow browing of past revisons in the File Browser
176
    /* Get any query strings */
177
    url = parse_url(window.location.href);
178
    
602 by mattgiuca
util.js: Added shallow_copy_object function.
179
    /* Call the server and request the listing. */
578 by dcoles
fileservice: Added code to allow browing of past revisons in the File Browser
180
    ajax_call(callback, service_app, path, url.args, "GET");
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
181
}
182
597 by mattgiuca
Major refactor of actions in File browser.
183
/* Refreshes the current view.
184
 * Calls navigate on the current path.
185
 */
186
function refresh()
187
{
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
188
    if (maybe_save('All changes since the last save will be lost!'))
189
        navigate(current_path);
597 by mattgiuca
Major refactor of actions in File browser.
190
}
191
211 by mattgiuca
fileservice/listing: Slight change to date format.
192
/** Determines the "handler type" from a MIME type.
193
 * The handler type is a string, either "text", "image", "audio" or "binary".
194
 */
195
function get_handler_type(content_type)
196
{
197
    if (!content_type)
198
        return null;
199
    if (content_type in type_handlers)
200
        return type_handlers[content_type];
201
    else
202
    {   /* Based on the first part of the MIME type */
203
        var handler_type = content_type.split('/')[0];
204
        if (handler_type != "text" && handler_type != "image" &&
205
            handler_type != "audio")
206
            handler_type = "binary";
207
        return handler_type;
208
    }
209
}
210
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
211
/** Given an HTTP response object, cleans up and rebuilds the contents of the
212
 * page using the response data. This does not navigate away from the page, it
213
 * merely rebuilds most of the data.
214
 * Note that depending on the type of data returned, this could result in a
215
 * directory listing, an image preview, an editor pane, etc.
216
 * Figures out the type and calls the appropriate function.
217
 * \param path URL path which the request was made for. This can (among other
218
 * things) be used to update the URL in the location bar.
219
 * \param response XMLHttpRequest object returned by the server. Should
220
 * contain all the response data.
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
221
 * \param is_action Boolean. True if this is the response to an action, false
222
 * if this is the response to a simple listing. This is used in handling the
223
 * error.
602 by mattgiuca
util.js: Added shallow_copy_object function.
224
 * \param url_args Arguments dict, for the arguments passed to the URL
225
 * in the browser's address bar (will be forwarded along).
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
226
 */
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
227
function handle_response(path, response, is_action, url_args)
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
228
{
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
229
    /* TODO: Set location bar to "path" */
211 by mattgiuca
fileservice/listing: Slight change to date format.
230
    current_path = path;
189 by mattgiuca
browser.js: Top-level handler now presents the path nav panel, not dir
231
232
    /* Clear away the existing page contents */
233
    clearpage();
234
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
235
    /* Check the status, and if not 200, read the error and handle this as an
236
     * error. */
237
    if (response.status != 200)
238
    {
239
        var error = response.getResponseHeader("X-IVLE-Return-Error");
240
        if (error == null)
241
            error = response.statusText;
242
        handle_error(error);
243
        return;
244
    }
245
944 by dcoles
Special Home Directory: Work to create a special home directory that shows the
246
    var subjects = null;
247
    var top_level_dir = path==username;
248
    if (top_level_dir)
249
    {
250
        var req = ajax_call(null, "userservice", "get_enrolments", null, "GET")
251
        subjects = decode_response(req);
252
    }
253
254
602 by mattgiuca
util.js: Added shallow_copy_object function.
255
    /* This will always return a listing, whether it is a dir or a file.
256
     */
257
    var listing = response.responseText;
258
    /* The listing SHOULD be valid JSON text. Parse it into an object. */
259
    try
260
    {
261
        listing = JSON.parse(listing);
262
        file_listing = listing.listing;     /* Global */
263
    }
264
    catch (e)
265
    {
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
266
        if (is_action)
267
        {
268
            var err = document.createElement("div");
269
            var p = dom_make_text_elem("p", "Error: "
270
                    + "There was an unexpected server error processing "
271
                    + "the selected command.");
272
            err.appendChild(p);
273
            p = dom_make_text_elem("p", "If the problem persists, please "
274
                    + "contact the system administrator.")
275
            err.appendChild(p);
276
            p = document.createElement("p");
277
            var refresh = document.createElement("input");
278
            refresh.setAttribute("type", "button");
279
            refresh.setAttribute("value", "Back to file view");
280
            refresh.setAttribute("onclick", "refresh()");
281
            p.appendChild(refresh);
282
            err.appendChild(p);
283
            handle_error(err);
284
        }
285
        else
286
        {
287
            var err = document.createElement("div");
288
            var p = dom_make_text_elem("p", "Error: "
289
                    + "There was an unexpected server error retrieving "
290
                    + "the requested file or directory.");
291
            err.appendChild(p);
292
            p = dom_make_text_elem("p", "If the problem persists, please "
293
                    + "contact the system administrator.")
294
            err.appendChild(p);
295
            handle_error(err);
296
        }
602 by mattgiuca
util.js: Added shallow_copy_object function.
297
        return;
298
    }
299
    /* Get "." out, it's special */
300
    current_file = file_listing["."];     /* Global */
301
    delete file_listing["."];
302
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
303
    if ('revision' in listing)
304
    {
305
        current_revision = listing.revision;
306
    }
307
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
308
    /* Check if this is a directory listing or file contents */
222 by mattgiuca
browser.js:
309
    var isdir = response.getResponseHeader("X-IVLE-Return") == "Dir";
602 by mattgiuca
util.js: Added shallow_copy_object function.
310
    if (isdir)
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
311
    {
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
312
        setup_for_listing();
313
        home_listing(listing, subjects, path);
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
314
    }
315
    else
316
    {
602 by mattgiuca
util.js: Added shallow_copy_object function.
317
        /* Need to make a 2nd ajax call, this time get the actual file
318
         * contents */
319
        callback = function(response)
320
            {
321
                /* Read the response and set up the page accordingly */
322
                handle_contents_response(path, response);
323
            }
324
        /* Call the server and request the listing. */
325
        if (url_args)
326
            args = shallow_clone_object(url_args);
327
        else
328
            args = {};
329
        /* This time, get the contents of the file, not its metadata */
330
        args['return'] = "contents";
331
        ajax_call(callback, service_app, path, args, "GET");
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
332
    }
597 by mattgiuca
Major refactor of actions in File browser.
333
    update_actions(isdir);
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
334
}
335
602 by mattgiuca
util.js: Added shallow_copy_object function.
336
function handle_contents_response(path, response)
337
{
338
    /* Treat this as an ordinary file. Get the file type. */
339
    var content_type = response.getResponseHeader("Content-Type");
340
    var handler_type = get_handler_type(content_type);
341
    would_be_handler_type = handler_type;
342
    /* handler_type should now be set to either
343
     * "text", "image", "audio" or "binary". */
344
    switch (handler_type)
345
    {
346
    case "text":
347
        handle_text(path, response.responseText,
348
            would_be_handler_type);
349
        break;
350
    case "image":
351
        /* TODO: Custom image handler */
352
        handle_binary(path, response.responseText);
353
        break;
354
    case "audio":
355
        /* TODO: Custom audio handler */
356
        handle_binary(path, response.responseText);
357
        break;
358
    case "binary":
359
        handle_binary(path);
360
        break;
361
    }
362
}
363
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
364
/* Called when a form upload comes back (from an iframe).
365
 * Refreshes the page.
366
 */
367
function upload_callback()
368
{
369
    /* This has a pretty nasty hack, which happens to work.
370
     * upload_callback is set as the "onload" callback for the iframe which
371
     * receives the response from the server for uploading a file.
372
     * This means it gets called twice. Once when initialising the iframe, and
373
     * a second time when the actual response comes back.
374
     * All we want to do is call navigate to refresh the page. But we CAN'T do
375
     * that on the first load or it will just go into an infinite cycle of
376
     * refreshing. We need to refresh the page ONLY on the second refresh.
377
     * upload_callback_count is reset to 0 just before the iframe is created.
378
     */
379
    upload_callback_count++;
380
    if (upload_callback_count >= 2)
838 by wagrant
browser.js: Clear the file upload path when an upload finishes.
381
    {
1089 by chadnickbok
Fixes Issue #14
382
        myFrame = frames['upload_iframe'].document;
1337 by William Grant
In the filebrowser upload callback, don't assume that the browser will generate a head element.
383
        /* Browsers will turn the raw returned JSON into an HTML document. We
384
         * need to get the <pre> from inside the <body>, and look at its text.
385
         */
386
        data = myFrame.firstChild.getElementsByTagName(
387
            'body')[0].firstChild.firstChild.nodeValue;
1089 by chadnickbok
Fixes Issue #14
388
        data = JSON.parse(data);
389
        if ('Error' in data)
390
            alert("Error: " + decodeURIComponent(data['Error']));
838 by wagrant
browser.js: Clear the file upload path when an upload finishes.
391
        document.getElementsByName('data')[0].value = '';
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
392
        refresh();
838 by wagrant
browser.js: Clear the file upload path when an upload finishes.
393
    }
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
394
}
395
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
396
/** Deletes all "dynamic" content on the page.
397
 * This returns the page back to the state it is in when the HTML arrives to
398
 * the browser, ready for another handler to populate it.
399
 */
400
function clearpage()
401
{
203 by mattgiuca
browser: Removed all directory-listing specific HTML from the Python-generated
402
    dom_removechildren(document.getElementById("filesbody"));
403
}
404
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
405
/* Checks if a file needs to be saved. If it does, the user will be asked
406
 * if they want to continue anyway. The caller must specify a warning
407
 * sentence which indicates the consequences of continuing.
408
 * Returns true if we should continue, and false if we should not.
409
 */
410
function maybe_save(warning)
411
{
412
    if (warning == null) warning = '';
413
    if (current_file.isdir) return true;
414
    if (document.getElementById("save_button").disabled) return true;
415
    return confirm("This file has unsaved changes. " + warning +
416
                   "\nAre you sure you wish to continue?");
417
}
418
203 by mattgiuca
browser: Removed all directory-listing specific HTML from the Python-generated
419
/** Deletes all "dynamic" content on the page necessary to navigate from
420
 * one directory listing to another (does not clear as much as clearpage
421
 * does).
422
 * This is the equivalent of calling clearpage() then
423
 * setup_for_dir_listing(), assuming the page is already on a dir listing.
424
 */
425
function clearpage_dir()
426
{
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
427
    dom_removechildren(document.getElementById("path"));
428
    dom_removechildren(document.getElementById("files"));
429
    dom_removechildren(document.getElementById("sidepanel"));
430
}
431
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
432
/*** HANDLERS for different types of responses (such as dir listing, file,
433
 * etc). */
434
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
435
/* handle_error.
436
 * message may either be a string, or a DOM node, which will be placed inside
437
 * a div.
438
 */
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
439
function handle_error(message)
440
{
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
441
    var files = document.getElementById("filesbody");
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
442
    var txt_elem;
443
    if (typeof(message) == "string")
444
    {
445
        txt_elem = dom_make_text_elem("div", "Error: "
446
                   + message.toString() + ".")
447
    }
448
    else
449
    {
450
        /* Assume message is a DOM node */
451
        txt_elem = document.createElement("div");
452
        txt_elem.appendChild(message);
453
    }
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
454
    txt_elem.setAttribute("class", "padding error");
455
    files.appendChild(txt_elem);
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
456
}
457
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
458
/** Given a path, filename and optional revision, returns a URL to open that
459
 *  revision of that file.
460
 */
461
function build_revision_url(path, filename, revision)
462
{
463
    bits = {'path': app_path(this_app, path, filename)};
464
    if (current_revision)
465
    {
466
        bits['query_string'] = 'r=' + revision;
467
    }
468
    return build_url(bits);
469
}
470
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
471
/** Given a mime type, returns the path to the icon.
472
 * \param type String, Mime type.
473
 * \param sizelarge Boolean, optional.
474
 * \return Path to the icon. Has applied make_path, so it is relative to site
475
 * root.
476
 */
477
function mime_type_to_icon(type, sizelarge)
478
{
479
    var filename;
480
    if (type in type_icons)
481
        filename = type_icons[type];
482
    else
483
        filename = default_type_icon;
484
    if (sizelarge)
485
        return make_path(path_join(type_icons_path_large, filename));
486
    else
487
        return make_path(path_join(type_icons_path, filename));
488
}
489
490
/** Given an svnstatus, returns the path to the icon.
491
 * \param type String, svn status.
492
 * \return Path to the icon. Has applied make_path, so it is relative to site
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
493
 * root. May return null to indicate no SVN icon.
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
494
 */
495
function svnstatus_to_icon(svnstatus)
496
{
497
    var filename;
498
    if (svnstatus in svn_icons)
499
        filename = svn_icons[svnstatus];
500
    else
501
        filename = default_svn_icon;
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
502
    if (filename == null) return null;
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
503
    return make_path(path_join(svn_icons_path, filename));
504
}
505
213 by mattgiuca
Fileservice / Files (Python and JS files):
506
/** Given an svnstatus, returns the "nice" string.
507
 */
508
function svnstatus_to_string(svnstatus)
509
{
510
    if (svnstatus in svn_nice)
511
        return svn_nice[svnstatus];
512
    else
513
        return default_svn_nice;
514
}
515
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
516
/** Displays a download link to the binary file.
517
 */
518
function handle_binary(path)
519
{
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
520
    var files = document.getElementById("filesbody");
521
    var div = document.createElement("div");
522
    files.appendChild(div);
523
    div.setAttribute("class", "padding");
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
524
    var download_link = app_path(download_app, path);
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
525
    var par1 = dom_make_text_elem("p",
526
        "The file " + path + " is a binary file. To download this file, " +
527
        "click the following link:");
528
    var par2 = dom_make_link_elem("p",
529
        "Download " + path, "Download " + path, download_link);
530
    div.appendChild(par1);
531
    div.appendChild(par2);
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
532
}
533
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
534
/* Enable or disable actions1 moreactions actions. Takes either a single
535
 * name, or an array of them.*/
908 by wagrant
browser: Link breadcrumbs to the current revision.
536
function set_action_state(names, which, allow_on_revision)
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
537
{
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
538
    if (!(names instanceof Array)) names = Array(names);
539
540
    for (var i=0; i < names.length; i++)
541
    {
542
        element = document.getElementById('act_' + names[i]);
908 by wagrant
browser: Link breadcrumbs to the current revision.
543
        if (which &&
544
            !(current_file.svnstatus == 'revision' && !allow_on_revision))
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
545
        {
546
            /* Enabling */
547
            element.setAttribute("class", "choice");
548
            element.removeAttribute("disabled");
549
        }
550
        else
551
        {
552
            /* Disabling */
553
            element.setAttribute("class", "disabled");
554
            element.setAttribute("disabled", "disabled");
555
        }
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
556
    }
557
}
558
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
559
/* Updates the list of available actions based on files selected */
597 by mattgiuca
Major refactor of actions in File browser.
560
function update_actions()
561
{
562
    var file;
563
    var numsel = selected_files.length;
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
564
    var svn_selection = false;
565
    
566
    if (numsel > 0)
567
    {
568
        svn_selection = true;
569
        for (var i = 0; i < selected_files.length; i++){
570
            if (file_listing[selected_files[i]]["svnstatus"] == "unversioned")
571
            {
572
                svn_selection = false;        
573
            }
574
        }
575
    }
576
    
597 by mattgiuca
Major refactor of actions in File browser.
577
    if (numsel <= 1)
578
    {
579
        if (numsel == 0)
580
        {
581
            /* Display information about the current directory instead */
582
            filename = path_basename(current_path);
602 by mattgiuca
util.js: Added shallow_copy_object function.
583
            file = current_file;
597 by mattgiuca
Major refactor of actions in File browser.
584
        }
585
        else if (numsel == 1)
586
        {
587
            filename = selected_files[0];
588
            file = file_listing[filename];
589
        }
590
591
        /* Update each action node in the topbar.
592
         * This includes enabling/disabling actions as appropriate, and
593
         * setting href/onclick attributes. */
594
    }
595
596
    /* Open */
597
    /* Available if exactly one file is selected */
598
    var open = document.getElementById("act_open");
599
    if (numsel == 1)
600
    {
601
        open.setAttribute("class", "choice");
602
        if (file.isdir)
603
            open.setAttribute("title",
604
                "Navigate to this directory in the file browser");
605
        else
606
            open.setAttribute("title",
607
                "Edit or view this file");
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
608
        open.setAttribute("href", build_revision_url(current_path, filename,
609
                                                     current_revision));
597 by mattgiuca
Major refactor of actions in File browser.
610
    }
611
    else
612
    {
613
        open.setAttribute("class", "disabled");
614
        open.removeAttribute("title");
615
        open.removeAttribute("href");
616
    }
617
618
    /* Serve */
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
619
    /* Available if zero or one files are selected,
597 by mattgiuca
Major refactor of actions in File browser.
620
     * and only if this is a file, not a directory */
621
    var serve = document.getElementById("act_serve");
908 by wagrant
browser: Link breadcrumbs to the current revision.
622
    if (numsel <= 1 && !file.isdir && current_file.svnstatus != 'revision')
597 by mattgiuca
Major refactor of actions in File browser.
623
    {
624
        serve.setAttribute("class", "choice");
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
625
        serve.setAttribute("onclick",
626
              "return maybe_save('The last saved version will be served.')");
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
627
        if (numsel == 0)
628
            serve.setAttribute("href",
629
                app_path(serve_app, current_path));
630
        else
631
            serve.setAttribute("href",
632
                app_path(serve_app, current_path, filename));
597 by mattgiuca
Major refactor of actions in File browser.
633
    }
634
    else
635
    {
636
        serve.setAttribute("class", "disabled");
637
        serve.removeAttribute("href");
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
638
        serve.removeAttribute("onclick");
597 by mattgiuca
Major refactor of actions in File browser.
639
    }
640
641
    /* Run */
642
    /* Available if exactly one file is selected,
643
     * and it is a Python file.
644
     */
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
645
    var run = document.getElementById("act_run");
646
     
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
647
    if (numsel <= 1 && !file.isdir && file.type == "text/x-python" 
648
            && current_file.svnstatus != 'revision')
873 by dcoles
Filebrowser: Clean up the javascript code a bit.
649
    {
650
        if (numsel == 0)
651
        {
652
            // In the edit window
653
            var localpath = path_join('/home', current_path);
654
        }
655
        else
656
        {
657
            // In the browser window
658
            var localpath = path_join('/home', current_path, filename);
659
        }
660
        run.setAttribute("class", "choice");
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
661
        run.setAttribute("onclick", "runfile('" + localpath + "')");
662
    }
663
    else
664
    {
665
        run.setAttribute("class", "disabled");
666
        run.removeAttribute("onclick");
667
    }
597 by mattgiuca
Major refactor of actions in File browser.
668
669
    /* Download */
908 by wagrant
browser: Link breadcrumbs to the current revision.
670
    /* Always available for current files.
597 by mattgiuca
Major refactor of actions in File browser.
671
     * If 0 files selected, download the current file or directory as a ZIP.
672
     * If 1 directory selected, download it as a ZIP.
673
     * If 1 non-directory selected, download it.
674
     * If >1 files selected, download them all as a ZIP.
675
     */
676
    var download = document.getElementById("act_download");
908 by wagrant
browser: Link breadcrumbs to the current revision.
677
    if (current_file.svnstatus == 'revision')
678
    {
679
        download.setAttribute("class", "disabled");
680
        download.removeAttribute("onclick");
681
    }
682
    else if (numsel <= 1)
683
    {
684
        download.setAttribute("class", "choice")
597 by mattgiuca
Major refactor of actions in File browser.
685
        if (numsel == 0)
686
        {
687
            download.setAttribute("href",
688
                app_path(download_app, current_path));
689
            if (file.isdir)
690
                download.setAttribute("title",
691
                    "Download the current directory as a ZIP file");
692
            else
693
                download.setAttribute("title",
694
                    "Download the current file");
695
        }
696
        else
697
        {
698
            download.setAttribute("href",
699
                app_path(download_app, current_path, filename));
700
            if (file.isdir)
701
                download.setAttribute("title",
702
                    "Download the selected directory as a ZIP file");
703
            else
704
                download.setAttribute("title",
705
                    "Download the selected file");
706
        }
707
    }
708
    else
709
    {
710
        /* Make a query string with all the files to download */
711
        var dlpath = urlencode_path(app_path(download_app, current_path)) + "?";
712
        for (var i=0; i<numsel; i++)
713
            dlpath += "path=" + encodeURIComponent(selected_files[i]) + "&";
714
        dlpath = dlpath.substr(0, dlpath.length-1);
908 by wagrant
browser: Link breadcrumbs to the current revision.
715
        download.setAttribute("class", "choice")
597 by mattgiuca
Major refactor of actions in File browser.
716
        download.setAttribute("href", dlpath);
717
        download.setAttribute("title",
718
            "Download the selected files as a ZIP file");
719
    }
720
721
    /* Refresh - No changes required */
722
723
    /* Publish and Submit */
724
    /* If this directory is under subversion and selected/unselected file is a
725
     * directory. */
726
    var publish = document.getElementById("act_publish");
727
    var submit = document.getElementById("act_submit");
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
728
    var pubcond = numsel <= 1 && file.isdir;
729
    if (pubcond)
597 by mattgiuca
Major refactor of actions in File browser.
730
    {
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
731
        /* If this dir is already published, call it "Unpublish" */
732
        if (file.published)
733
        {
734
            publish.setAttribute("value", "unpublish");
735
            publish.setAttribute("title" ,"Make it so this directory "
736
                + "can not be seen by anyone on the web");
1171 by William Grant
Replace all uses of .textContent with .nodeValue.
737
            publish.firstChild.nodeValue = "Unpublish";
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
738
        } else {
739
            publish.setAttribute("value", "publish");
740
            publish.setAttribute("title","Make it so this directory "
741
                + "can be seen by anyone on the web");
1171 by William Grant
Replace all uses of .textContent with .nodeValue.
742
            publish.firstChild.nodeValue = "Publish";
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
743
        }
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
744
    }
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
745
    set_action_state(["publish", "submit"], pubcond);
597 by mattgiuca
Major refactor of actions in File browser.
746
747
    /* Share */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
748
    /* If exactly 1 non-directory file is selected, and its parent
597 by mattgiuca
Major refactor of actions in File browser.
749
     * directory is published.
750
     */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
751
    set_action_state("share", numsel == 1 && !file.isdir &&
752
                     current_file.published);
597 by mattgiuca
Major refactor of actions in File browser.
753
754
    /* Rename */
755
    /* If exactly 1 file is selected */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
756
    set_action_state("rename", numsel == 1);
597 by mattgiuca
Major refactor of actions in File browser.
757
758
    /* Delete, cut, copy */
759
    /* If >= 1 file is selected */
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
760
    set_action_state(["delete", "cut", "copy"], numsel >= 1);
597 by mattgiuca
Major refactor of actions in File browser.
761
762
    /* Paste, new file, new directory, upload */
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
763
    /* Disable if the current file is not a directory */
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
764
    set_action_state(["paste", "newfile", "mkdir", "upload"], current_file.isdir);
597 by mattgiuca
Major refactor of actions in File browser.
765
766
    /* Subversion actions */
829 by wagrant
Add an svndiff action, and give it an option in the action listbox.
767
    /* These are only useful if we are in a versioned directory and have some
768
     * files selected. */
1167 by William Grant
Remove an extra comma from browser.js.
769
    set_action_state(["svnadd"], numsel >= 1 && current_file.svnstatus);
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
770
    /* And these are only usefull is ALL the selected files are versioned */
771
    set_action_state(["svnremove", "svnrevert", "svncommit", "svncopy", 
772
            "svncut"], numsel >= 1 && current_file.svnstatus && svn_selection);
773
    
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
774
    /* Diff, log and update only support one path at the moment, so we must
775
     * have 0 or 1 versioned files selected. If 0, the directory must be
776
     * versioned. */
881 by wagrant
browser.js: Support svndiff and svnlog for versioned directories. Also
777
    single_versioned_path = (
778
         (
779
          (numsel == 1 && (svnst = file_listing[selected_files[0]].svnstatus)) ||
780
          (numsel == 0 && (svnst = current_file.svnstatus))
781
         ) && svnst != "unversioned");
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
782
    set_action_state(["svndiff", "svnupdate"], single_versioned_path);
908 by wagrant
browser: Link breadcrumbs to the current revision.
783
919 by wagrant
fileservice_lib: Implement "svn resolved".
784
    /* We can resolve if we have a file selected and it is conflicted. */
785
    set_action_state("svnresolved", single_versioned_path && numsel == 1 && svnst == "conflicted");
786
908 by wagrant
browser: Link breadcrumbs to the current revision.
787
    /* Log should be available for revisions as well. */
788
    set_action_state("svnlog", single_versioned_path, true);
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
789
1318.1.2 by David Coles
Add Subversion Cleanup to web UI
790
    /* Cleanup should be available for revisions as well. */
791
    set_action_state("svncleanup", single_versioned_path, true);
792
1165.1.33 by William Grant
Enable the Submit filebrowser action only when we have exactly one target
793
    single_ivle_versioned_path = (
794
         (
795
          (numsel == 1 && (stat = file_listing[selected_files[0]])) ||
796
          (numsel == 0 && (stat = current_file))
797
         ) && stat.svnstatus != "unversioned"
1165.1.37 by William Grant
Check that stat.svnurl exists before using parts of it to enable the Submit action.
798
           && stat.svnurl
1165.1.33 by William Grant
Enable the Submit filebrowser action only when we have exactly one target
799
           && stat.svnurl.substr(0, svn_base.length) == svn_base);
800
    set_action_state(["submit"], single_ivle_versioned_path);
801
777 by mattgiuca
browser: Now hides the "More actions" box altogether if the current file is
802
    /* There is currently nothing on the More Actions menu of use
803
     * when the current file is not a directory. Hence, just remove
804
     * it entirely.
805
     * (This makes some of the above decisions somewhat redundant).
834 by wagrant
Let the client decide whether to show file or directory actions2, as
806
     * We also take this opportunity to show the appropriate actions2
807
     * bar for this path. It should either be a save or upload widget.
777 by mattgiuca
browser: Now hides the "More actions" box altogether if the current file is
808
     */
834 by wagrant
Let the client decide whether to show file or directory actions2, as
809
    if (current_file.isdir)
810
    {
811
        var actions2_directory = document.getElementById("actions2_directory");
812
        actions2_directory.setAttribute("style", "display: inline;");
911 by wagrant
browser: Hide 'More Actions' by default. It will be shown by JS when
813
        var moreactions = document.getElementById("moreactions_area");
814
        moreactions.setAttribute("style", "display: inline;");
834 by wagrant
Let the client decide whether to show file or directory actions2, as
815
    }
816
    else
817
    {
818
        var actions2_file = document.getElementById("actions2_file");
819
        actions2_file.setAttribute("style", "display: inline;");
777 by mattgiuca
browser: Now hides the "More actions" box altogether if the current file is
820
    }
821
597 by mattgiuca
Major refactor of actions in File browser.
822
    return;
823
}
824
825
/** Event handler for when an item of the "More actions..." dropdown box is
826
 * selected. Performs the selected action. */
827
function handle_moreactions()
828
{
829
    var moreactions = document.getElementById("moreactions");
830
    if (moreactions.value == "top")
831
        return;
832
    var selectedaction = moreactions.value;
833
    /* Reset to "More actions..." */
834
    moreactions.selectedIndex = 0;
835
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
836
    /* If 0 files selected, filename is the name of the current dir.
837
     * If 1 file selected, filename is that file.
838
     */
839
    if (selected_files.length == 0)
840
        filename = path_basename(current_path);
841
    else if (selected_files.length == 1)
842
        filename = selected_files[0];
843
    else
844
        filename = null;
845
597 by mattgiuca
Major refactor of actions in File browser.
846
    /* Now handle the selected action */
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
847
    switch(selectedaction)
848
    {
849
    case "publish":
850
        action_publish(selected_files);
851
        break;
852
    case "unpublish":
853
        action_unpublish(selected_files);
854
        break;
855
    case "share":
1099.1.204 by William Grant
"Share this file" in the file browser points to the new-style publicserveview.
856
        window.open(public_app_path("~" + current_path, filename), 'share')
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
857
        break;
858
    case "submit":
1165.1.35 by William Grant
Implement the Submit filebrowser action.
859
        if (selected_files.length == 1)
860
            stat = file_listing[selected_files[0]];
861
        else
862
            stat = current_file;
863
        path = stat.svnurl.substr(svn_base.length);
1165.1.40 by William Grant
When submitting, query the server about the latest revision of the path.
864
865
        /* The working copy might not have an up-to-date version of the
866
         * directory. While submitting like this could yield unexpected
867
         * results, we should really submit the latest revision to minimise
868
         * terrible mistakes - so we run off and ask fileservice for the
869
         * latest revision.*/
870
        $.post(app_path(service_app, current_path),
871
            {"action": "svnrepostat", "path": path},
872
            function(result)
873
            {
874
                window.location = path_join(app_path('+submit'), path) + '?revision=' + result.svnrevision;
875
            },
876
            "json");
877
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
878
        break;
879
    case "rename":
880
        action_rename(filename);
881
        break;
882
    case "delete":
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
883
        action_delete(selected_files);
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
884
        break;
885
    case "copy":
886
        action_copy(selected_files);
887
        break;
888
    case "cut":
889
        action_cut(selected_files);
890
        break;
891
    case "paste":
892
        action_paste();
893
        break;
894
    case "newfile":
611 by mattgiuca
"New File" now works. (This is a MUCH better replacement for having to go to
895
        action_newfile();
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
896
        break;
897
    case "mkdir":
898
        action_mkdir();
899
        break;
900
    case "upload":
901
        show_uploadpanel(true);
902
        break;
903
    case "svnadd":
904
        action_add(selected_files);
905
        break;
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
906
    case "svnremove":
907
        action_remove(selected_files);
908
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
909
    case "svnrevert":
910
        action_revert(selected_files);
911
        break;
829 by wagrant
Add an svndiff action, and give it an option in the action listbox.
912
    case "svndiff":
881 by wagrant
browser.js: Support svndiff and svnlog for versioned directories. Also
913
        window.location = path_join(app_path('diff'), current_path, selected_files[0] || '');
829 by wagrant
Add an svndiff action, and give it an option in the action listbox.
914
        break;
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
915
    case "svnupdate":
916
        action_update(selected_files);
917
        break;
919 by wagrant
fileservice_lib: Implement "svn resolved".
918
    case "svnresolved":
919
        action_resolved(selected_files);
920
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
921
    case "svncommit":
922
        action_commit(selected_files);
923
        break;
832 by wagrant
Add svnlog to the file actions dropdown.
924
    case "svnlog":
881 by wagrant
browser.js: Support svndiff and svnlog for versioned directories. Also
925
        window.location = path_join(app_path('svnlog'), current_path, selected_files[0] || '');
832 by wagrant
Add svnlog to the file actions dropdown.
926
        break;
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
927
    case "svncopy":
928
        action_svncopy(selected_files);
929
        break;
930
    case "svncut":
931
        action_svncut(selected_files);
932
        break;
1318.1.2 by David Coles
Add Subversion Cleanup to web UI
933
    case "svncleanup":
934
        action_svncleanup(".");
935
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
936
    }
597 by mattgiuca
Major refactor of actions in File browser.
937
}
938
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
939
/** User clicks "Run" button.
940
 * Do an Ajax call and print the test output.
941
 */
942
function runfile(localpath)
943
{
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
944
    if (!maybe_save('The last saved version will be run.')) return false;
945
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
946
    /* Dump the entire file to the console */
947
    var callback = function()
948
    {
949
        console_enter_line("execfile('" + localpath + "')", "block");
950
    }
951
    start_server(callback)
952
    return;
953
}
954
170 by mattgiuca
browser: Added CSS and JS files (not much in them).
955
/** Called when the page loads initially.
956
 */
849 by dcoles
Browser: Ported Browser to the new scripts_init framework. Started to decouple
957
function browser_init()
170 by mattgiuca
browser: Added CSS and JS files (not much in them).
958
{
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
959
    /* Navigate (internally) to the path in the URL bar.
960
     * This causes the page to be populated with whatever is at that address,
961
     * whether it be a directory or a file.
962
     */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
963
    var path = get_path();
964
    navigate(path);
965
}
966
1339 by William Grant
Revert client-side parts of r1333; reliance on the deprecated tab mechanism is to be avoided.
967
/** Gets the current path of the window */
968
function get_path() {
969
    var path = parse_url(window.location.href).path;
970
    /* Strip out root_dir + "/files" from the front of the path */
971
    var strip = make_path(this_app);
972
    if (path.substr(0, strip.length) == strip)
973
        path = path.substr(strip.length+1);
974
    else
975
    {
976
        /* See if this is an edit path */
977
        strip = make_path(edit_app);
978
        if (path.substr(0, strip.length) == strip)
979
        {
980
            path = path.substr(strip.length+1);
981
        }
982
    }
983
984
    if (path.length == 0)
985
    {
986
        /* Navigate to the user's home directory by default */
987
        /* TEMP? */
988
        path = username;
989
    }
990
991
    return path;
992
}