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