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