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

209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
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: Listing (File Browser, client)
19
 * Author: Matt Giuca
20
 * Date: 13/1/2008
21
 *
22
 * Handles directory listings on the client side.
23
 */
24
234 by mattgiuca
browser/listing.js:
25
/* Note: The DOM "tr" nodes of the file listing have extra attributes added
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
26
 * to them:
27
 *  filename: String.
28
 *  fileinfo: The file object as returned by the server.
29
 */
215 by mattgiuca
listing.js:
30
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
31
/* DOM nodeType constants */
32
ELEMENT_NODE = 1;
33
34
/** Filenames of all files selected */
35
selected_files = [];
36
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
37
/** The listing object returned by the server as JSON */
38
file_listing = null;
211 by mattgiuca
fileservice/listing: Slight change to date format.
39
thisdir = null;
40
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
41
/** The current sort order (a list of fields to sort by, in order of
42
 * priority), and whether it is ascending or descending. */
43
sort_order = [];
44
sort_ascending = true;
45
229 by mattgiuca
Images: Reduced "small" icons from 22x22 to 16x16. Reduced "large" icons from
46
/** The width/height of filetype, svnstatus and publishstatus icons */
47
icon_size = 16;
48
215 by mattgiuca
listing.js:
49
/** ACTIONS **/
50
51
function action_rename(fromfilename)
52
{
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
53
    var tofilename = prompt("Rename file \"" + fromfilename + "\" to?");
215 by mattgiuca
listing.js:
54
    if (tofilename == null) return;
55
    do_action("move", current_path, {"from":fromfilename, "to":tofilename});
56
    return false;
57
}
58
59
function action_remove(files)
60
{
61
    do_action("remove", current_path, {"path":files});
62
    return false;
63
}
64
65
function action_copy(files)
66
{
67
    do_action("copy", current_path, {"path":files});
68
    return false;
69
}
70
71
function action_cut(files)
72
{
73
    do_action("cut", current_path, {"path":files});
74
    return false;
75
}
76
77
function action_paste()
78
{
79
    do_action("paste", current_path, {"path":"."});
80
    return false;
81
}
82
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
83
function action_add(files)
84
{
85
    do_action("svnadd", current_path, {"path":files});
86
    return false;
87
}
88
89
function action_revert(files)
90
{
91
    do_action("svnrevert", current_path, {"path":files});
92
    return false;
93
}
94
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
95
function action_publish(files)
96
{
97
    do_action("svnpublish", current_path, {"path":files});
98
    return false;
99
}
100
101
function action_unpublish(files)
102
{
103
    do_action("svnunpublish", current_path, {"path":files});
104
    return false;
105
}
106
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
107
function action_commit(files)
108
{
109
    /* Get a commit log from the user */
110
    var logmsg = prompt("Enter commit log:");
223 by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths.
111
    if (logmsg == null) return;
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
112
    do_action("svncommit", current_path, {"path":files, "logmsg": logmsg});
113
    return false;
114
}
115
215 by mattgiuca
listing.js:
116
/** END ACTIONS **/
117
211 by mattgiuca
fileservice/listing: Slight change to date format.
118
/** Updates the side-panel. Expects selected_files reflects the current
119
 * selected files.
120
 */
121
function update_sidepanel(total_file_size_sel)
122
{
123
    var sidepanel = document.getElementById("sidepanel");
124
    var filename;
125
    var file;
126
    var p;
127
    /* Is this dir under svn? */
128
    var under_subversion = "svnstatus" in thisdir;
129
    dom_removechildren(sidepanel);
130
    if (selected_files.length <= 1)
131
    {
132
        if (selected_files.length == 0)
133
        {
134
            /* Display information about the current directory instead */
135
            filename = path_basename(current_path);
136
            file = thisdir;
137
        }
138
        else if (selected_files.length == 1)
139
        {
215 by mattgiuca
listing.js:
140
            filename = selected_files[0];
211 by mattgiuca
fileservice/listing: Slight change to date format.
141
            file = file_listing[filename];
142
        }
143
        var filetype;
144
        if ("isdir" in file && file.isdir)
145
            filetype = "text/directory";
146
        else if ("type" in file)
147
            filetype = file.type;
148
        else
149
            filetype = "text/plain";
150
213 by mattgiuca
Fileservice / Files (Python and JS files):
151
        if ("type_nice" in file)
152
            filetype_nice = file.type_nice;
153
        else
154
            filetype_nice = "File";
155
211 by mattgiuca
fileservice/listing: Slight change to date format.
156
        p = document.createElement("p");
157
        sidepanel.appendChild(p);
158
        p.appendChild(dom_make_img(mime_type_to_icon(filetype, true),
159
            null, null, filetype));
160
        p = dom_make_text_elem("h2", filename);
161
        sidepanel.appendChild(p);
213 by mattgiuca
Fileservice / Files (Python and JS files):
162
        p = dom_make_text_elem("p", filetype_nice);
211 by mattgiuca
fileservice/listing: Slight change to date format.
163
        sidepanel.appendChild(p);
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
164
        var mini_icons = document.createElement("p");
165
        sidepanel.appendChild(mini_icons);
166
        var icon;
213 by mattgiuca
Fileservice / Files (Python and JS files):
167
        if (under_subversion)
168
        {
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
169
            icon = svnstatus_to_icon(file.svnstatus);
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
170
            if (icon)
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
171
                mini_icons.appendChild(dom_make_img(icon, icon_size, icon_size,
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
172
                    svnstatus_to_string(file.svnstatus)));
213 by mattgiuca
Fileservice / Files (Python and JS files):
173
            p = dom_make_text_elem("p", svnstatus_to_string(file.svnstatus));
174
            sidepanel.appendChild(p);
175
        }
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
176
        if ("published" in file && file.published)
177
        {
178
            icon = make_path(path_join(published_icon));
179
            if (icon)
180
            {
181
                if (mini_icons.childNodes.length > 0)
182
                    mini_icons.appendChild(document.createTextNode(" "));
183
                mini_icons.appendChild(dom_make_img(icon, icon_size, icon_size,
327 by mattgiuca
browser: Renamed "Published directory" label to "Published to the web".
184
                    "Published to the web"));
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
185
            }
327 by mattgiuca
browser: Renamed "Published directory" label to "Published to the web".
186
            p = dom_make_text_elem("p", "Published to the web");
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
187
            p.setAttribute("title",
188
                "Anybody on the web can view the files in this directory.");
189
            sidepanel.appendChild(p);
190
        }
191
        /* If we never wrote any mini-icons, remove this element */
192
        if (mini_icons.childNodes.length == 0)
193
            sidepanel.removeChild(mini_icons);
211 by mattgiuca
fileservice/listing: Slight change to date format.
194
        if ("size" in file)
195
        {
196
            p = dom_make_text_elem("p", "Size: " + nice_filesize(file.size));
197
            sidepanel.appendChild(p);
198
        }
199
        if ("mtime_nice" in file)
200
        {
201
            p = dom_make_text_elem("p", "Modified: " + file.mtime_nice);
202
            sidepanel.appendChild(p);
203
        }
204
    }
205
    else
206
    {
207
        /* Multiple files selected */
208
        p = document.createElement("p");
209
        sidepanel.appendChild(p);
210
        p.appendChild(dom_make_img(
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
211
            app_path(type_icons_path_large, "multi.png"),
211 by mattgiuca
fileservice/listing: Slight change to date format.
212
            null, null, "Multiple files"));
213
        p = dom_make_text_elem("h2",
214
            selected_files.length.toString() + " files selected");
215
        sidepanel.appendChild(p);
216
        p = dom_make_text_elem("p", "Total size: "
217
            + nice_filesize(total_file_size_sel));
218
        sidepanel.appendChild(p);
219
    }
220
221
    p = dom_make_text_elem("h3", "Actions");
222
    sidepanel.appendChild(p);
223
224
    if (selected_files.length <= 1)
225
    {
330 by mattgiuca
browser/listing.js: Bugfix - error on multiple files selected when updating
226
        if (file.isdir)
227
        {
228
            /* Publish/unpublish */
229
            if (selected_files.length == 0)
230
                path = ".";
231
            else
232
                path = filename;
233
            if ("published" in file && file.published)
234
            {
235
                p = dom_make_link_elem("p", "Unpublish",
236
                    "Make it so this directory cannot be seen by anyone but you",
237
                    null,
238
                    "return action_unpublish(" + repr(path) + ")");
239
                sidepanel.appendChild(p);
240
            }
241
            else
242
            {
243
                p = dom_make_link_elem("p", "Publish",
244
                    "Make it so this directory can be seen by anyone on the web",
245
                    null,
246
                    "return action_publish(" + repr(path) + ")");
247
                sidepanel.appendChild(p);
248
            }
249
        }
250
211 by mattgiuca
fileservice/listing: Slight change to date format.
251
        var handler_type = null;
252
        if ("type" in file)
253
            handler_type = get_handler_type(file.type);
254
        /* Action: Use the "files" / "edit" app */
215 by mattgiuca
listing.js:
255
        var path;
256
        if (selected_files.length == 1)
257
        {
258
            /* Don't have "Browse" if this is the current dir */
259
            if (file.isdir)
260
                p = dom_make_link_elem("p", "Browse",
261
                    "Navigate to this directory in the file browser",
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
262
                    app_path(this_app, current_path, filename));
215 by mattgiuca
listing.js:
263
            else if (handler_type == "text")
264
                p = dom_make_link_elem("p", "Edit", "Edit this file",
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
265
                    app_path(edit_app, current_path, filename));
215 by mattgiuca
listing.js:
266
            else
267
                p = dom_make_link_elem("p", "Browse",
268
                    "View this file in the file browser",
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
269
                    app_path(this_app, current_path, filename));
215 by mattgiuca
listing.js:
270
            sidepanel.appendChild(p);
271
        }
211 by mattgiuca
fileservice/listing: Slight change to date format.
272
273
        /* Action: Use the "serve" app */
274
        /* TODO: Figure out if this file is executable,
275
         * and change the link to "Run" */
276
        p = null;
277
        if (file.isdir || handler_type == "binary") {}
278
        else
279
            p = dom_make_link_elem("p", "View",
215 by mattgiuca
listing.js:
280
                "View this file",
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
281
                app_path(serve_app, current_path, filename));
211 by mattgiuca
fileservice/listing: Slight change to date format.
282
        if (p)
283
            sidepanel.appendChild(p);
284
285
        /* Action: Use the "download" app */
286
        p = null;
242 by mattgiuca
browser/listing: Fix: Download link for current directory, wrong path.
287
        if (selected_files.length == 0)
288
            path = app_path(download_app, current_path);
289
        else
290
            path = app_path(download_app, current_path, filename);
211 by mattgiuca
fileservice/listing: Slight change to date format.
291
        if (file.isdir)
292
            p = dom_make_link_elem("p", "Download as zip",
215 by mattgiuca
listing.js:
293
                "Download this directory as a ZIP file", path);
211 by mattgiuca
fileservice/listing: Slight change to date format.
294
        else
295
            p = dom_make_link_elem("p", "Download",
215 by mattgiuca
listing.js:
296
                "Download this file to your computer", path);
211 by mattgiuca
fileservice/listing: Slight change to date format.
297
        if (p)
298
            sidepanel.appendChild(p);
299
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
300
        if (selected_files.length > 0)
301
        {   /* Can't rename if we're in it */
302
            p = dom_make_link_elem("p", "Rename",
303
                "Change the name of this file", null,
304
                "return action_rename(" + repr(filename) + ")");
305
            sidepanel.appendChild(p);
306
        }
211 by mattgiuca
fileservice/listing: Slight change to date format.
307
    }
308
    else
309
    {
241 by mattgiuca
util.js: dom_make_link_elem: Added argument dontencode, necessary to sometimes
310
        path = urlencode_path(app_path(download_app, current_path)) + "?";
215 by mattgiuca
listing.js:
311
        for (var i=0; i<selected_files.length; i++)
312
            path += "path=" + encodeURIComponent(selected_files[i]) + "&";
313
        path = path.substr(0, path.length-1);
211 by mattgiuca
fileservice/listing: Slight change to date format.
314
        /* Multiple files selected */
315
        p = dom_make_link_elem("p", "Download as zip",
241 by mattgiuca
util.js: dom_make_link_elem: Added argument dontencode, necessary to sometimes
316
            "Download the selected files as a ZIP file", path, null, true);
211 by mattgiuca
fileservice/listing: Slight change to date format.
317
        sidepanel.appendChild(p);
318
    }
319
320
    /* Common actions */
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
321
    if (selected_files.length > 0)
322
    {
323
        p = dom_make_link_elem("p", "Delete",
324
            "Delete the selected files", null,
325
            "return action_remove(selected_files)");
326
        sidepanel.appendChild(p);
327
        p = dom_make_link_elem("p", "Cut",
328
            "Prepare to move the selected files to another directory", null,
329
            "return action_cut(selected_files)");
330
        sidepanel.appendChild(p);
331
        p = dom_make_link_elem("p", "Copy",
332
            "Prepare to copy the selected files to another directory", null,
333
            "return action_copy(selected_files)");
334
        sidepanel.appendChild(p);
335
    }
211 by mattgiuca
fileservice/listing: Slight change to date format.
336
    p = dom_make_link_elem("p", "Paste",
215 by mattgiuca
listing.js:
337
        "Paste the copied or cut files to the current directory", null,
338
        "return action_paste()");
211 by mattgiuca
fileservice/listing: Slight change to date format.
339
    sidepanel.appendChild(p);
340
341
    if (under_subversion)
342
    {
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
343
        /* TODO: Only show relevant links */
211 by mattgiuca
fileservice/listing: Slight change to date format.
344
        p = dom_make_text_elem("h3", "Subversion");
345
        sidepanel.appendChild(p);
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
346
347
        /* TODO: if any selected files are unversioned */
348
        p = dom_make_link_elem("p", "Add",
349
            "Schedule the selected temporary files to be added permanently",
350
            null,
351
            "return action_add(selected_files)");
352
        sidepanel.appendChild(p);
353
        p = dom_make_link_elem("p", "Revert",
354
            "Restore the selected files back to their last committed state",
355
            null,
356
            "return action_revert(selected_files)");
357
        sidepanel.appendChild(p);
358
        /* TODO: Update */
359
        p = dom_make_link_elem("p", "Commit",
360
            "Commit any changes to the permanent repository",
361
            null,
362
            "return action_commit(selected_files)");
363
        sidepanel.appendChild(p);
211 by mattgiuca
fileservice/listing: Slight change to date format.
364
    }
365
366
}
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
367
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
368
/** Updates the side-panel and status bar to reflect the current set of
369
 * selected files. This is done by inspecting the states of the check boxes.
370
 * Also changes the styling to highlight selected files.
371
 */
372
function update_selection()
373
{
374
    /* First get a list of all files that are selected, and
375
     * reset the styling on each file's row. */
376
    var files_children = document.getElementById("files").childNodes;
377
    var tr;
378
    var checkbox;
379
    var row_toggle = 1;
380
    selected_files = [];  /* Clear global selected_files */
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
381
382
    var total_file_size = 0;    /* In bytes */
383
    var total_file_size_sel = 0;
384
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
385
    /* Children are trs */
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
386
    var filename;
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
387
    var file;
388
    if (file_listing == null) return;
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
389
    for (var i=0; i<files_children.length; i++)
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
390
    {
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
391
        filename = files_children[i].filename;
392
        file = files_children[i].fileinfo;
393
        /* Count total file size so we can write to the status bar later
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
394
         */
395
        if ("size" in file)
396
            total_file_size += file.size;
397
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
398
        tr = files_children[i];
399
        checked = tr.firstChild.firstChild.checked;
400
        /* Set the class for every row based on both the checked state,
401
         * and whether it is odd or even */
402
        tr.setAttribute("class", "row" + row_toggle.toString() +
403
            (checked ? "sel" : ""))
404
        row_toggle = row_toggle == 1 ? 2 : 1;
405
        if (checked)
406
        {
407
            /* Add the filename (column 3) to the selected_files list */
408
            selected_files[selected_files.length] = filename;
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
409
            if ("size" in file)
410
                total_file_size_sel += file.size;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
411
        }
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
412
    }
413
211 by mattgiuca
fileservice/listing: Slight change to date format.
414
    /* Write to the side-panel */
415
    update_sidepanel(total_file_size_sel);
416
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
417
    /* Write to the status bar */
418
    var statusbar = document.getElementById("statusbar");
419
    var statusmsg;
420
    var file_plural;
421
    if (selected_files.length > 0)
422
    {
423
        statusmsg = selected_files.length.toString() + " file"
424
            + (selected_files.length == 1 ? "" : "s") + " selected, "
425
            + nice_filesize(total_file_size_sel);
426
    }
427
    else
428
    {
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
429
        statusmsg = files_children.length.toString() + " file"
430
            + (files_children.length == 1 ? "" : "s") + ", "
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
431
            + nice_filesize(total_file_size);
432
    }
433
    dom_removechildren(statusbar);
434
    statusbar.appendChild(document.createTextNode(statusmsg));
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
435
}
436
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
437
/** SORTING FUNCTIONS **/
438
439
/** Sorts the file table. Physically manipulates the DOM table to reflect the
440
 * sorted nodes, and also updates the little sort arrow.
441
 *
442
 * \param sort_field The name of the field to sort on primarily. This can
443
 * either be "filename", or one of the fields of a fileinfo object. Note that
444
 * while this determines the primary sort key, the secondary sort keys are
445
 * determined by the global sort_order. Calling sort_listing reorders
446
 * sort_order, bringing the specified sort_field to the top.
447
 * Also note that sorting by "isdir" is more prominent than whatever field is
448
 * provided here.
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
449
 * \param ascending If true, sorts ascending. If false, descending.
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
450
 */
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
451
function sort_listing(sort_field, ascending)
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
452
{
453
    var i;
454
    var files = document.getElementById("files");
455
    var files_children = files.childNodes;
456
    var files_array = new Array(files_children.length);
457
    /* Update sort_order, bringing sort_field to the top. */
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
458
    sort_order.removeall(sort_field);
459
    sort_order.push(sort_field);
460
    sort_ascending = ascending != false ? true : false;
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
461
462
    /* Build an array of DOM tr elements (with the additional 'filename' and
463
     * 'fileinfo' attributes as written when the listing is created). */
464
    /* Note: Must manually create an array from files_children, which is a DOM
465
     * NodeList, not an array. */
466
    for (i=0; i<files_children.length; i++)
467
        files_array[i] = files_children[i];
468
469
    /* Sort this array */
470
    files_array.sort(compare_files);
471
472
    /* Clean out the table (the TRs are safely stored in the array) */
473
    dom_removechildren(files);
474
475
    /* Insert the TRs back into the table, in their sorted order */
476
    for (i=0; i<files_array.length; i++)
477
        files.appendChild(files_array[i]);
478
479
    /* Fix the coloring classes on the rows so they are interleaved. */
480
    update_selection();
481
482
    return false;
483
}
484
485
/** Comparison function used for sorting. Compares two DOM tr nodes (with
486
 * the additional 'filename' and 'fileinfo' attributes as written when the
487
 * listing is created).
488
 * Returns an integer, which is -1 if a < b, 0 if a == b, and 1 if a > b.
489
 * The fields to compare by are determined by the global variable sort_order.
490
 */
491
function compare_files(a, b)
492
{
236 by mattgiuca
listing.js: Correct sorting by directory. (Now sorts all directories to the
493
    /* First sort by whether or not it is a directory */
494
    var aisdir = a.fileinfo.isdir == true;
495
    var bisdir = b.fileinfo.isdir == true;
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
496
    var LESS = sort_ascending == true ? -1 : 1;
497
    var GREATER = -LESS;
498
    if (aisdir > bisdir) return LESS;
499
    else if (aisdir < bisdir) return GREATER;
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
500
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
501
    /* Reverse order of sort_order. (top is highest priority) */
502
    for (var i=sort_order.length-1; i>=0; i--)
503
    {
504
        var field = sort_order[i];
505
        if (field == "filename")
506
        {
507
            if (a.filename < b.filename) return LESS;
508
            else if (a.filename > b.filename) return GREATER;
509
        }
510
        else
511
        {
512
            /* null > anything else (so it appears at the bottom) */
513
            if (!(field in a))
514
                if (field in b) return GREATER; else break;
515
            if (!(field in b)) return LESS;
516
            if (a.fileinfo[field] < b.fileinfo[field]) return LESS;
517
            else if (a.fileinfo[field] > b.fileinfo[field]) return GREATER;
518
        }
519
    }
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
520
521
    return 0;
522
}
523
524
/** END SORTING **/
525
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
526
/** Clears all selected files and causes the single file specified to become
527
 * selected.
234 by mattgiuca
browser/listing.js:
528
 * \param filename The file in the list to select.
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
529
 */
234 by mattgiuca
browser/listing.js:
530
function select_file(filename)
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
531
{
532
    var files_children = document.getElementById("files").childNodes;
533
    var checkbox;
234 by mattgiuca
browser/listing.js:
534
    var tr;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
535
    for (var i=0; i<files_children.length; i++)
536
    {
537
        tr = files_children[i];
538
        checkbox = tr.firstChild.firstChild;
234 by mattgiuca
browser/listing.js:
539
        checkbox.checked = tr.filename == filename;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
540
    }
541
    update_selection();
542
}
543
544
/** Initialises the DOM elements required to present a dir listing,
545
 * assuming that clear_page has just been called or the page just
546
 * loaded for the first time.
547
 */
548
function setup_for_dir_listing()
549
{
550
    var filesbody = document.getElementById("filesbody");
551
552
    /* Using a table-based layout, for reasons of sanity */
553
    /* One row, 2 columns */
554
    var middle = document.createElement("table");
555
    filesbody.appendChild(middle);
556
    middle.setAttribute("id", "middle");
557
    var middle_tbody = document.createElement("tbody");
558
    middle.appendChild(middle_tbody);
559
    var middle_tr = document.createElement("tr");
560
    middle_tbody.appendChild(middle_tr);
561
562
    /* Column 1: File table */
563
    var filetable = document.createElement("td");
564
    middle_tr.appendChild(filetable);
565
    filetable.setAttribute("id", "filetable");
566
    var filetablediv = document.createElement("div");
567
    filetable.appendChild(filetablediv);
568
    filetablediv.setAttribute("id", "filetablediv");
569
    /* A nested table within this div - the actual files listing */
570
    var filetabletable = document.createElement("table");
571
    filetablediv.appendChild(filetabletable);
572
    filetabletable.setAttribute("width", "100%");
573
    var filetablethead = document.createElement("thead");
574
    filetabletable.appendChild(filetablethead);
575
    var filetablethead_tr = document.createElement("tr");
576
    filetablethead.appendChild(filetablethead_tr);
577
    filetablethead_tr.setAttribute("class", "rowhead");
578
    /* Row headers */
579
    var filetablethead_th = document.createElement("th");
580
    filetablethead_tr.appendChild(filetablethead_th);
581
    filetablethead_th.setAttribute("class", "col-check");
582
    filetablethead_th = dom_make_link_elem("th", "Filename",
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
583
        "Sort by filename", null, "return sort_listing(\"filename\")");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
584
    filetablethead_tr.appendChild(filetablethead_th);
585
    filetablethead_th.setAttribute("class", "col-filename");
586
    filetablethead_th.setAttribute("colspan", 3);
587
    filetablethead_th = dom_make_link_elem("th", "Size",
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
588
        "Sort by file size", null, "return sort_listing(\"size\")");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
589
    filetablethead_tr.appendChild(filetablethead_th);
590
    filetablethead_th.setAttribute("class", "col-size");
591
    filetablethead_th = dom_make_link_elem("th", "Modified",
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
592
        "Sort by date modified", null, "return sort_listing(\"mtime\")");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
593
    filetablethead_tr.appendChild(filetablethead_th);
594
    filetablethead_th.setAttribute("class", "col-date");
595
    /* Empty body */
596
    var filetabletbody = document.createElement("tbody");
597
    filetabletable.appendChild(filetabletbody);
598
    filetabletbody.setAttribute("id", "files");
599
600
    /* Column 2: Side-panel */
601
    var sidepanel = document.createElement("td");
602
    middle_tr.appendChild(sidepanel);
603
    sidepanel.setAttribute("id", "sidepanel");
604
605
606
    /* Now after the table "middle", there is a status bar */
607
    var statusbar = document.createElement("div");
608
    filesbody.appendChild(statusbar);
609
    statusbar.setAttribute("id", "statusbar");
610
}
611
612
/** Presents the directory listing.
613
 */
614
function handle_dir_listing(path, listing)
615
{
616
    setmode(false);
617
    setup_for_dir_listing();
618
    var row_toggle = 1;
619
    /* Nav through the top-level of the JSON to the actual listing object. */
620
    var listing = listing.listing;
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
621
    file_listing = listing;     /* Global */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
622
623
    /* Get "." out, it's special */
211 by mattgiuca
fileservice/listing: Slight change to date format.
624
    thisdir = listing["."];     /* Global */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
625
    delete listing["."];
626
    /* Is this dir under svn? */
627
    var under_subversion = "svnstatus" in thisdir;
628
629
    var files = document.getElementById("files");
630
    var file;
631
    var row;
632
    var td;
633
    var checkbox;
634
635
    var selection_string;
636
637
    /* Create all of the files */
638
    for (var filename in listing)
639
    {
234 by mattgiuca
browser/listing.js:
640
        selection_string = "select_file(" + repr(filename) + ")";
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
641
        file = listing[filename];
234 by mattgiuca
browser/listing.js:
642
        /* Make a 'tr' element. Store the filename and fileinfo in
643
         * here. */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
644
        row = document.createElement("tr");
234 by mattgiuca
browser/listing.js:
645
        row.filename = filename;
646
        row.fileinfo = file;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
647
        /* Column 1: Selection checkbox */
648
        row.setAttribute("class", "row" + row_toggle.toString())
649
        row_toggle = row_toggle == 1 ? 2 : 1;
650
        td = document.createElement("td");
651
        checkbox = document.createElement("input");
652
        checkbox.setAttribute("type", "checkbox");
653
        checkbox.setAttribute("title", "Select this file");
654
        checkbox.setAttribute("onchange", "update_selection()");
655
        td.appendChild(checkbox);
656
        row.appendChild(td);
657
        if (file.isdir)
658
        {
659
            /* Column 2: Filetype and subversion icons. */
660
            td = document.createElement("td");
661
            td.setAttribute("class", "thincol");
662
            td.setAttribute("onclick", selection_string);
663
            td.appendChild(dom_make_img(mime_type_to_icon("text/directory"),
229 by mattgiuca
Images: Reduced "small" icons from 22x22 to 16x16. Reduced "large" icons from
664
                icon_size, icon_size, file.type_nice));
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
665
            row.appendChild(td);
666
            td = document.createElement("td");
667
            td.setAttribute("class", "thincol");
668
            if (under_subversion)
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
669
            {
670
                var icon = svnstatus_to_icon(file.svnstatus);
671
                if (icon)
672
                    td.appendChild(dom_make_img(icon, icon_size, icon_size,
673
                        svnstatus_to_string(file.svnstatus)));
674
            }
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
675
            row.appendChild(td);
676
            /* Column 3: Filename */
677
            td = dom_make_link_elem("td", filename,
678
                "Navigate to " + path_join(path, filename),
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
679
                app_path(this_app, path, filename)/*,
215 by mattgiuca
listing.js:
680
                "navigate(" + repr(path_join(path, filename)) + ")"*/);
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
681
            td.setAttribute("onclick", selection_string);
682
            row.appendChild(td);
683
        }
684
        else
685
        {
686
            /* Column 2: Filetype and subversion icons. */
687
            td = document.createElement("td");
688
            td.setAttribute("class", "thincol");
689
            td.appendChild(dom_make_img(mime_type_to_icon(file.type),
229 by mattgiuca
Images: Reduced "small" icons from 22x22 to 16x16. Reduced "large" icons from
690
                icon_size, icon_size, file.type_nice));
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
691
            row.appendChild(td);
692
            td = document.createElement("td");
693
            td.setAttribute("class", "thincol");
694
            if (under_subversion)
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
695
            {
696
                var icon = svnstatus_to_icon(file.svnstatus);
697
                if (icon)
698
                    td.appendChild(dom_make_img(icon, icon_size, icon_size,
699
                        svnstatus_to_string(file.svnstatus)));
700
            }
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
701
            row.appendChild(td);
702
            /* Column 3: Filename */
703
            td = dom_make_text_elem("td", filename);
704
            td.setAttribute("onclick", selection_string);
705
            row.appendChild(td);
706
        }
707
        /* Column 4: Size */
708
        td = dom_make_text_elem("td", nice_filesize(file.size));
709
        td.setAttribute("onclick", selection_string);
710
        row.appendChild(td);
711
        /* Column 4: Date */
712
        td = dom_make_text_elem("td", file.mtime_short, file.mtime_nice);
713
        td.setAttribute("onclick", selection_string);
714
        row.appendChild(td);
715
        files.appendChild(row);
716
    }
717
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
718
    /* Apply an initial sort by filename */
719
    sort_listing("filename");
720
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
721
    /* Do a selection update (create initial elements for side panel and
722
     * status bar). */
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
723
    /* Commented out; already called by sort_listing */
724
    /*update_selection();*/
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
725
}
726