~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
         */
1791 by David Coles
Use innerText || innerContent to get contents of iframe. Should prevent an odd
401
        var pre = myFrame.firstChild.getElementsByTagName(
402
            'body')[0].firstChild;
403
        var data = pre.innerText || pre.textContent;
1089 by chadnickbok
Fixes Issue #14
404
        data = JSON.parse(data);
405
        if ('Error' in data)
406
            alert("Error: " + decodeURIComponent(data['Error']));
838 by wagrant
browser.js: Clear the file upload path when an upload finishes.
407
        document.getElementsByName('data')[0].value = '';
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
408
        refresh();
838 by wagrant
browser.js: Clear the file upload path when an upload finishes.
409
    }
622 by mattgiuca
browser.js: Reinstated upload_callback (previously removed from listing.js).
410
}
411
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
412
/** Deletes all "dynamic" content on the page.
413
 * This returns the page back to the state it is in when the HTML arrives to
414
 * the browser, ready for another handler to populate it.
415
 */
416
function clearpage()
417
{
203 by mattgiuca
browser: Removed all directory-listing specific HTML from the Python-generated
418
    dom_removechildren(document.getElementById("filesbody"));
419
}
420
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
421
/* Checks if a file needs to be saved. If it does, the user will be asked
422
 * if they want to continue anyway. The caller must specify a warning
423
 * sentence which indicates the consequences of continuing.
424
 * Returns true if we should continue, and false if we should not.
425
 */
426
function maybe_save(warning)
427
{
428
    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.
429
    if (current_file == null || current_file.isdir) return true;
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
430
    if (document.getElementById("save_button").disabled) return true;
431
    return confirm("This file has unsaved changes. " + warning +
432
                   "\nAre you sure you wish to continue?");
433
}
434
203 by mattgiuca
browser: Removed all directory-listing specific HTML from the Python-generated
435
/** Deletes all "dynamic" content on the page necessary to navigate from
436
 * one directory listing to another (does not clear as much as clearpage
437
 * does).
438
 * This is the equivalent of calling clearpage() then
439
 * setup_for_dir_listing(), assuming the page is already on a dir listing.
440
 */
441
function clearpage_dir()
442
{
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
443
    dom_removechildren(document.getElementById("path"));
444
    dom_removechildren(document.getElementById("files"));
445
    dom_removechildren(document.getElementById("sidepanel"));
446
}
447
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
448
/*** HANDLERS for different types of responses (such as dir listing, file,
449
 * etc). */
450
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
451
/* handle_error.
452
 * message may either be a string, or a DOM node, which will be placed inside
453
 * a div.
454
 */
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
455
function handle_error(message)
456
{
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
457
    var files = document.getElementById("filesbody");
789 by mattgiuca
browser.js: Replaced the old "The server returned an invalid directory
458
    var txt_elem;
459
    if (typeof(message) == "string")
460
    {
461
        txt_elem = dom_make_text_elem("div", "Error: "
462
                   + message.toString() + ".")
463
    }
464
    else
465
    {
466
        /* Assume message is a DOM node */
467
        txt_elem = document.createElement("div");
468
        txt_elem.appendChild(message);
469
    }
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
470
    txt_elem.setAttribute("class", "padding error");
471
    files.appendChild(txt_elem);
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
472
}
473
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
474
/** Given a path, filename and optional revision, returns a URL to open that
475
 *  revision of that file.
476
 */
477
function build_revision_url(path, filename, revision)
478
{
479
    bits = {'path': app_path(this_app, path, filename)};
480
    if (current_revision)
481
    {
482
        bits['query_string'] = 'r=' + revision;
483
    }
484
    return build_url(bits);
485
}
486
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
487
/** Given a mime type, returns the path to the icon.
488
 * \param type String, Mime type.
489
 * \param sizelarge Boolean, optional.
490
 * \return Path to the icon. Has applied make_path, so it is relative to site
491
 * root.
492
 */
493
function mime_type_to_icon(type, sizelarge)
494
{
495
    var filename;
496
    if (type in type_icons)
497
        filename = type_icons[type];
498
    else
499
        filename = default_type_icon;
500
    if (sizelarge)
501
        return make_path(path_join(type_icons_path_large, filename));
502
    else
503
        return make_path(path_join(type_icons_path, filename));
504
}
505
506
/** Given an svnstatus, returns the path to the icon.
507
 * \param type String, svn status.
508
 * \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
509
 * root. May return null to indicate no SVN icon.
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
510
 */
511
function svnstatus_to_icon(svnstatus)
512
{
513
    var filename;
514
    if (svnstatus in svn_icons)
515
        filename = svn_icons[svnstatus];
516
    else
517
        filename = default_svn_icon;
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
518
    if (filename == null) return null;
190 by mattgiuca
util: Added function dom_make_img, creates <img> elements.
519
    return make_path(path_join(svn_icons_path, filename));
520
}
521
213 by mattgiuca
Fileservice / Files (Python and JS files):
522
/** Given an svnstatus, returns the "nice" string.
523
 */
524
function svnstatus_to_string(svnstatus)
525
{
526
    if (svnstatus in svn_nice)
527
        return svn_nice[svnstatus];
528
    else
529
        return default_svn_nice;
530
}
531
1662 by Matt Giuca
browser.js, listing.js: Abstract testing svn status against 'unversioned' to svnstatus_versioned function.
532
/** Returns true if a file is versioned (not unversioned or ignored).
533
 */
534
function svnstatus_versioned(svnstatus)
535
{
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.
536
    return svnstatus != "unversioned" && svnstatus != "ignored";
1662 by Matt Giuca
browser.js, listing.js: Abstract testing svn status against 'unversioned' to svnstatus_versioned function.
537
}
538
183 by mattgiuca
browser: Added top level of response handling. Now determines handler type and
539
/** Displays a download link to the binary file.
540
 */
541
function handle_binary(path)
542
{
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
543
    var files = document.getElementById("filesbody");
544
    var div = document.createElement("div");
545
    files.appendChild(div);
546
    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.
547
    var download_link = app_url(download_app, path);
205 by mattgiuca
browser.js: Added appropriate handlers for error, text, and binary data.
548
    var par1 = dom_make_text_elem("p",
549
        "The file " + path + " is a binary file. To download this file, " +
550
        "click the following link:");
551
    var par2 = dom_make_link_elem("p",
552
        "Download " + path, "Download " + path, download_link);
553
    div.appendChild(par1);
554
    div.appendChild(par2);
181 by mattgiuca
browser.js: Added functions do_action, navigate, handle_response (stubs).
555
}
556
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
557
/* Enable or disable actions1 moreactions actions. Takes either a single
558
 * name, or an array of them.*/
908 by wagrant
browser: Link breadcrumbs to the current revision.
559
function set_action_state(names, which, allow_on_revision)
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
560
{
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
561
    if (!(names instanceof Array)) names = Array(names);
562
563
    for (var i=0; i < names.length; i++)
564
    {
565
        element = document.getElementById('act_' + names[i]);
908 by wagrant
browser: Link breadcrumbs to the current revision.
566
        if (which &&
567
            !(current_file.svnstatus == 'revision' && !allow_on_revision))
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
568
        {
569
            /* Enabling */
570
            element.setAttribute("class", "choice");
571
            element.removeAttribute("disabled");
572
        }
573
        else
574
        {
575
            /* Disabling */
576
            element.setAttribute("class", "disabled");
577
            element.setAttribute("disabled", "disabled");
578
        }
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
579
    }
580
}
581
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
582
/* Updates the list of available actions based on files selected */
597 by mattgiuca
Major refactor of actions in File browser.
583
function update_actions()
584
{
585
    var file;
586
    var numsel = selected_files.length;
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
587
    var svn_selection = false;
588
    
589
    if (numsel > 0)
590
    {
591
        svn_selection = true;
592
        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.
593
            if (!svnstatus_versioned(file_listing[selected_files[i]].svnstatus))
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
594
            {
1662 by Matt Giuca
browser.js, listing.js: Abstract testing svn status against 'unversioned' to svnstatus_versioned function.
595
                svn_selection = false;
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
596
            }
597
        }
598
    }
599
    
597 by mattgiuca
Major refactor of actions in File browser.
600
    if (numsel <= 1)
601
    {
602
        if (numsel == 0)
603
        {
604
            /* Display information about the current directory instead */
605
            filename = path_basename(current_path);
602 by mattgiuca
util.js: Added shallow_copy_object function.
606
            file = current_file;
597 by mattgiuca
Major refactor of actions in File browser.
607
        }
608
        else if (numsel == 1)
609
        {
610
            filename = selected_files[0];
611
            file = file_listing[filename];
612
        }
613
614
        /* Update each action node in the topbar.
615
         * This includes enabling/disabling actions as appropriate, and
616
         * setting href/onclick attributes. */
617
    }
618
619
    /* Open */
620
    /* Available if exactly one file is selected */
621
    var open = document.getElementById("act_open");
622
    if (numsel == 1)
623
    {
624
        open.setAttribute("class", "choice");
625
        if (file.isdir)
626
            open.setAttribute("title",
627
                "Navigate to this directory in the file browser");
628
        else
629
            open.setAttribute("title",
630
                "Edit or view this file");
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
631
        open.setAttribute("href", build_revision_url(current_path, filename,
632
                                                     current_revision));
597 by mattgiuca
Major refactor of actions in File browser.
633
    }
634
    else
635
    {
636
        open.setAttribute("class", "disabled");
637
        open.removeAttribute("title");
638
        open.removeAttribute("href");
639
    }
640
641
    /* Serve */
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
642
    /* Available if zero or one files are selected,
597 by mattgiuca
Major refactor of actions in File browser.
643
     * and only if this is a file, not a directory */
644
    var serve = document.getElementById("act_serve");
908 by wagrant
browser: Link breadcrumbs to the current revision.
645
    if (numsel <= 1 && !file.isdir && current_file.svnstatus != 'revision')
597 by mattgiuca
Major refactor of actions in File browser.
646
    {
647
        serve.setAttribute("class", "choice");
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
648
        serve.setAttribute("onclick",
649
              "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.
650
        if (numsel == 0)
651
            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.
652
                app_url(serve_app, current_path));
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
653
        else
654
            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.
655
                app_url(serve_app, current_path, filename));
597 by mattgiuca
Major refactor of actions in File browser.
656
    }
657
    else
658
    {
659
        serve.setAttribute("class", "disabled");
660
        serve.removeAttribute("href");
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
661
        serve.removeAttribute("onclick");
597 by mattgiuca
Major refactor of actions in File browser.
662
    }
663
664
    /* Run */
665
    /* Available if exactly one file is selected,
666
     * and it is a Python file.
667
     */
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
668
    var run = document.getElementById("act_run");
669
     
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
670
    if (numsel <= 1 && !file.isdir && file.type == "text/x-python" 
671
            && current_file.svnstatus != 'revision')
873 by dcoles
Filebrowser: Clean up the javascript code a bit.
672
    {
673
        if (numsel == 0)
674
        {
675
            // In the edit window
676
            var localpath = path_join('/home', current_path);
677
        }
678
        else
679
        {
680
            // In the browser window
681
            var localpath = path_join('/home', current_path, filename);
682
        }
683
        run.setAttribute("class", "choice");
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
684
        run.setAttribute("onclick", "runfile('" + localpath + "')");
685
    }
686
    else
687
    {
688
        run.setAttribute("class", "disabled");
689
        run.removeAttribute("onclick");
690
    }
597 by mattgiuca
Major refactor of actions in File browser.
691
692
    /* Download */
908 by wagrant
browser: Link breadcrumbs to the current revision.
693
    /* Always available for current files.
597 by mattgiuca
Major refactor of actions in File browser.
694
     * If 0 files selected, download the current file or directory as a ZIP.
695
     * If 1 directory selected, download it as a ZIP.
696
     * If 1 non-directory selected, download it.
697
     * If >1 files selected, download them all as a ZIP.
698
     */
699
    var download = document.getElementById("act_download");
908 by wagrant
browser: Link breadcrumbs to the current revision.
700
    if (current_file.svnstatus == 'revision')
701
    {
702
        download.setAttribute("class", "disabled");
703
        download.removeAttribute("onclick");
704
    }
705
    else if (numsel <= 1)
706
    {
707
        download.setAttribute("class", "choice")
597 by mattgiuca
Major refactor of actions in File browser.
708
        if (numsel == 0)
709
        {
710
            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.
711
                app_url(download_app, current_path));
597 by mattgiuca
Major refactor of actions in File browser.
712
            if (file.isdir)
713
                download.setAttribute("title",
714
                    "Download the current directory as a ZIP file");
715
            else
716
                download.setAttribute("title",
717
                    "Download the current file");
718
        }
719
        else
720
        {
721
            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.
722
                app_url(download_app, current_path, filename));
597 by mattgiuca
Major refactor of actions in File browser.
723
            if (file.isdir)
724
                download.setAttribute("title",
725
                    "Download the selected directory as a ZIP file");
726
            else
727
                download.setAttribute("title",
728
                    "Download the selected file");
729
        }
730
    }
731
    else
732
    {
733
        /* 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.
734
        var dlpath = app_url(download_app, current_path) + "?";
597 by mattgiuca
Major refactor of actions in File browser.
735
        for (var i=0; i<numsel; i++)
736
            dlpath += "path=" + encodeURIComponent(selected_files[i]) + "&";
737
        dlpath = dlpath.substr(0, dlpath.length-1);
908 by wagrant
browser: Link breadcrumbs to the current revision.
738
        download.setAttribute("class", "choice")
597 by mattgiuca
Major refactor of actions in File browser.
739
        download.setAttribute("href", dlpath);
740
        download.setAttribute("title",
741
            "Download the selected files as a ZIP file");
742
    }
743
744
    /* Refresh - No changes required */
745
746
    /* Publish and Submit */
747
    /* If this directory is under subversion and selected/unselected file is a
748
     * directory. */
749
    var publish = document.getElementById("act_publish");
750
    var submit = document.getElementById("act_submit");
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
751
    var pubcond = numsel <= 1 && file.isdir;
752
    if (pubcond)
597 by mattgiuca
Major refactor of actions in File browser.
753
    {
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
754
        /* If this dir is already published, call it "Unpublish" */
755
        if (file.published)
756
        {
757
            publish.setAttribute("value", "unpublish");
758
            publish.setAttribute("title" ,"Make it so this directory "
759
                + "can not be seen by anyone on the web");
1171 by William Grant
Replace all uses of .textContent with .nodeValue.
760
            publish.firstChild.nodeValue = "Unpublish";
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
761
        } else {
762
            publish.setAttribute("value", "publish");
763
            publish.setAttribute("title","Make it so this directory "
764
                + "can be seen by anyone on the web");
1171 by William Grant
Replace all uses of .textContent with .nodeValue.
765
            publish.firstChild.nodeValue = "Publish";
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
766
        }
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
767
    }
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
768
    set_action_state(["publish", "submit"], pubcond);
597 by mattgiuca
Major refactor of actions in File browser.
769
770
    /* Share */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
771
    /* If exactly 1 non-directory file is selected, and its parent
597 by mattgiuca
Major refactor of actions in File browser.
772
     * directory is published.
773
     */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
774
    set_action_state("share", numsel == 1 && !file.isdir &&
775
                     current_file.published);
597 by mattgiuca
Major refactor of actions in File browser.
776
777
    /* Rename */
778
    /* If exactly 1 file is selected */
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
779
    set_action_state("rename", numsel == 1);
597 by mattgiuca
Major refactor of actions in File browser.
780
781
    /* Delete, cut, copy */
782
    /* If >= 1 file is selected */
863 by wagrant
browser: Let set_action_state take an Array of names as well. We now
783
    set_action_state(["delete", "cut", "copy"], numsel >= 1);
597 by mattgiuca
Major refactor of actions in File browser.
784
785
    /* Paste, new file, new directory, upload */
775 by mattgiuca
browser.js: Updated logic to decide when to enable/disable certain actions.
786
    /* 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
787
    set_action_state(["paste", "newfile", "mkdir", "upload"], current_file.isdir);
597 by mattgiuca
Major refactor of actions in File browser.
788
789
    /* Subversion actions */
829 by wagrant
Add an svndiff action, and give it an option in the action listbox.
790
    /* These are only useful if we are in a versioned directory and have some
791
     * files selected. */
1804 by David Coles
Added Subversion rename to Filebrowser.
792
    set_action_state(["svnrename"], numsel == 1 && current_file.svnstatus);
1167 by William Grant
Remove an extra comma from browser.js.
793
    set_action_state(["svnadd"], numsel >= 1 && current_file.svnstatus);
1664 by Matt Giuca
browser.js: Adjusted condition for enabling "Commit" action; now allowed if
794
    /* And these are only useful is ALL the selected files are versioned */
795
    set_action_state(["svnremove", "svnrevert", "svncopy", "svncut"],
796
            numsel >= 1 && current_file.svnstatus && svn_selection);
797
    /* Commit is useful if ALL selected files are versioned, or the current
798
     * directory is versioned */
799
    set_action_state(["svncommit"], current_file.svnstatus &&
800
            (numsel >= 1 && svn_selection || numsel == 0));
801
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
802
    /* Diff, log and update only support one path at the moment, so we must
803
     * have 0 or 1 versioned files selected. If 0, the directory must be
804
     * versioned. */
881 by wagrant
browser.js: Support svndiff and svnlog for versioned directories. Also
805
    single_versioned_path = (
806
         (
807
          (numsel == 1 && (svnst = file_listing[selected_files[0]].svnstatus)) ||
808
          (numsel == 0 && (svnst = current_file.svnstatus))
1662 by Matt Giuca
browser.js, listing.js: Abstract testing svn status against 'unversioned' to svnstatus_versioned function.
809
         ) && svnstatus_versioned(svnst));
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
810
    set_action_state(["svndiff", "svnupdate"], single_versioned_path);
908 by wagrant
browser: Link breadcrumbs to the current revision.
811
919 by wagrant
fileservice_lib: Implement "svn resolved".
812
    /* We can resolve if we have a file selected and it is conflicted. */
813
    set_action_state("svnresolved", single_versioned_path && numsel == 1 && svnst == "conflicted");
814
908 by wagrant
browser: Link breadcrumbs to the current revision.
815
    /* Log should be available for revisions as well. */
816
    set_action_state("svnlog", single_versioned_path, true);
862 by wagrant
browser: Refactor the client-side actions1 processing! Kill off 100 lines
817
1318.1.2 by David Coles
Add Subversion Cleanup to web UI
818
    /* Cleanup should be available for revisions as well. */
819
    set_action_state("svncleanup", single_versioned_path, true);
820
1165.1.33 by William Grant
Enable the Submit filebrowser action only when we have exactly one target
821
    single_ivle_versioned_path = (
822
         (
823
          (numsel == 1 && (stat = file_listing[selected_files[0]])) ||
824
          (numsel == 0 && (stat = current_file))
1662 by Matt Giuca
browser.js, listing.js: Abstract testing svn status against 'unversioned' to svnstatus_versioned function.
825
         ) && 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.
826
           && stat.svnurl
1165.1.33 by William Grant
Enable the Submit filebrowser action only when we have exactly one target
827
           && stat.svnurl.substr(0, svn_base.length) == svn_base);
828
    set_action_state(["submit"], single_ivle_versioned_path);
829
777 by mattgiuca
browser: Now hides the "More actions" box altogether if the current file is
830
    /* There is currently nothing on the More Actions menu of use
831
     * when the current file is not a directory. Hence, just remove
832
     * it entirely.
833
     * (This makes some of the above decisions somewhat redundant).
834 by wagrant
Let the client decide whether to show file or directory actions2, as
834
     * We also take this opportunity to show the appropriate actions2
835
     * 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
836
     */
834 by wagrant
Let the client decide whether to show file or directory actions2, as
837
    if (current_file.isdir)
838
    {
839
        var actions2_directory = document.getElementById("actions2_directory");
840
        actions2_directory.setAttribute("style", "display: inline;");
911 by wagrant
browser: Hide 'More Actions' by default. It will be shown by JS when
841
        var moreactions = document.getElementById("moreactions_area");
842
        moreactions.setAttribute("style", "display: inline;");
834 by wagrant
Let the client decide whether to show file or directory actions2, as
843
    }
844
    else
845
    {
846
        var actions2_file = document.getElementById("actions2_file");
847
        actions2_file.setAttribute("style", "display: inline;");
777 by mattgiuca
browser: Now hides the "More actions" box altogether if the current file is
848
    }
849
597 by mattgiuca
Major refactor of actions in File browser.
850
    return;
851
}
852
853
/** Event handler for when an item of the "More actions..." dropdown box is
854
 * selected. Performs the selected action. */
855
function handle_moreactions()
856
{
857
    var moreactions = document.getElementById("moreactions");
858
    if (moreactions.value == "top")
859
        return;
860
    var selectedaction = moreactions.value;
861
    /* Reset to "More actions..." */
862
    moreactions.selectedIndex = 0;
863
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
864
    /* If 0 files selected, filename is the name of the current dir.
865
     * If 1 file selected, filename is that file.
866
     */
867
    if (selected_files.length == 0)
868
        filename = path_basename(current_path);
869
    else if (selected_files.length == 1)
870
        filename = selected_files[0];
871
    else
872
        filename = null;
873
597 by mattgiuca
Major refactor of actions in File browser.
874
    /* Now handle the selected action */
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
875
    switch(selectedaction)
876
    {
877
    case "publish":
878
        action_publish(selected_files);
879
        break;
880
    case "unpublish":
881
        action_unpublish(selected_files);
882
        break;
883
    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.
884
        window.open(public_app_url("~" + current_path, filename), 'share')
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
885
        break;
886
    case "submit":
1165.1.35 by William Grant
Implement the Submit filebrowser action.
887
        if (selected_files.length == 1)
888
            stat = file_listing[selected_files[0]];
889
        else
890
            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.
891
        url = stat.svnurl.substr(svn_base.length);      // URL-encoded
892
        path = decodeURIComponent(url);
1165.1.40 by William Grant
When submitting, query the server about the latest revision of the path.
893
894
        /* The working copy might not have an up-to-date version of the
895
         * directory. While submitting like this could yield unexpected
896
         * results, we should really submit the latest revision to minimise
897
         * terrible mistakes - so we run off and ask fileservice for the
898
         * latest revision.*/
899
        $.post(app_path(service_app, current_path),
900
            {"action": "svnrepostat", "path": path},
901
            function(result)
902
            {
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.
903
                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.
904
            },
905
            "json");
906
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
907
        break;
908
    case "rename":
909
        action_rename(filename);
910
        break;
911
    case "delete":
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
912
        action_delete(selected_files);
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
913
        break;
914
    case "copy":
915
        action_copy(selected_files);
916
        break;
917
    case "cut":
918
        action_cut(selected_files);
919
        break;
920
    case "paste":
921
        action_paste();
922
        break;
923
    case "newfile":
611 by mattgiuca
"New File" now works. (This is a MUCH better replacement for having to go to
924
        action_newfile();
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
925
        break;
926
    case "mkdir":
927
        action_mkdir();
928
        break;
929
    case "upload":
930
        show_uploadpanel(true);
931
        break;
932
    case "svnadd":
933
        action_add(selected_files);
934
        break;
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
935
    case "svnremove":
1804 by David Coles
Added Subversion rename to Filebrowser.
936
        action_svnremove(selected_files);
937
        break;
938
    case "svnrename":
939
        action_svnrename(selected_files);
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
940
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
941
    case "svnrevert":
942
        action_revert(selected_files);
943
        break;
829 by wagrant
Add an svndiff action, and give it an option in the action listbox.
944
    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.
945
        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.
946
        break;
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
947
    case "svnupdate":
948
        action_update(selected_files);
949
        break;
919 by wagrant
fileservice_lib: Implement "svn resolved".
950
    case "svnresolved":
951
        action_resolved(selected_files);
952
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
953
    case "svncommit":
954
        action_commit(selected_files);
955
        break;
832 by wagrant
Add svnlog to the file actions dropdown.
956
    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.
957
        window.location = path_join(app_url('svnlog'), current_path, selected_files[0] || '');
832 by wagrant
Add svnlog to the file actions dropdown.
958
        break;
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
959
    case "svncopy":
960
        action_svncopy(selected_files);
961
        break;
962
    case "svncut":
963
        action_svncut(selected_files);
964
        break;
1318.1.2 by David Coles
Add Subversion Cleanup to web UI
965
    case "svncleanup":
966
        action_svncleanup(".");
967
        break;
607 by mattgiuca
browser/browser.js: All the actions in "more actions" now actually take
968
    }
597 by mattgiuca
Major refactor of actions in File browser.
969
}
970
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
971
/** User clicks "Run" button.
972
 * Do an Ajax call and print the test output.
973
 */
974
function runfile(localpath)
975
{
865 by wagrant
browser: Warn users before running, serving and refreshing if the file
976
    if (!maybe_save('The last saved version will be run.')) return false;
977
713 by dcoles
browser: Added console and run button to allow Python files to be executed in
978
    /* Dump the entire file to the console */
979
    var callback = function()
980
    {
981
        console_enter_line("execfile('" + localpath + "')", "block");
982
    }
983
    start_server(callback)
984
    return;
985
}
986
170 by mattgiuca
browser: Added CSS and JS files (not much in them).
987
/** Called when the page loads initially.
988
 */
849 by dcoles
Browser: Ported Browser to the new scripts_init framework. Started to decouple
989
function browser_init()
170 by mattgiuca
browser: Added CSS and JS files (not much in them).
990
{
188 by mattgiuca
browser.js: Can now (shakily) handle directory listings. (lots of code!)
991
    /* Navigate (internally) to the path in the URL bar.
992
     * This causes the page to be populated with whatever is at that address,
993
     * whether it be a directory or a file.
994
     */
1326.1.2 by David Coles
Small refactor of browser's JavaScript to allow do_action to be called from
995
    var path = get_path();
996
    navigate(path);
997
}
998
1339 by William Grant
Revert client-side parts of r1333; reliance on the deprecated tab mechanism is to be avoided.
999
/** Gets the current path of the window */
1000
function get_path() {
1001
    var path = parse_url(window.location.href).path;
1002
    /* Strip out root_dir + "/files" from the front of the path */
1003
    var strip = make_path(this_app);
1004
    if (path.substr(0, strip.length) == strip)
1005
        path = path.substr(strip.length+1);
1006
    else
1007
    {
1008
        /* See if this is an edit path */
1009
        strip = make_path(edit_app);
1010
        if (path.substr(0, strip.length) == strip)
1011
        {
1012
            path = path.substr(strip.length+1);
1013
        }
1014
    }
1015
1016
    if (path.length == 0)
1017
    {
1018
        /* Navigate to the user's home directory by default */
1019
        /* TEMP? */
1020
        path = username;
1021
    }
1022
1023
    return path;
1024
}