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