~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
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
34
/** The current sort order (a list of fields to sort by, in order of
35
 * priority), and whether it is ascending or descending. */
36
sort_order = [];
37
sort_ascending = true;
38
229 by mattgiuca
Images: Reduced "small" icons from 22x22 to 16x16. Reduced "large" icons from
39
/** The width/height of filetype, svnstatus and publishstatus icons */
40
icon_size = 16;
41
215 by mattgiuca
listing.js:
42
/** ACTIONS **/
43
44
function action_rename(fromfilename)
45
{
683 by mattgiuca
browser/listing.js: When the "rename" dialog comes up, the default text is
46
    var tofilename = prompt("Rename file \"" + fromfilename + "\" to?",
47
        fromfilename);
215 by mattgiuca
listing.js:
48
    if (tofilename == null) return;
49
    do_action("move", current_path, {"from":fromfilename, "to":tofilename});
50
    return false;
51
}
52
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
53
function action_delete(files)
215 by mattgiuca
listing.js:
54
{
614 by mattgiuca
browser/listing: Added a confirmation message for deleting files
55
    var conf_msg;
56
    /* A heavy nesty bit of logic to determine the confirmation message.
57
     */
58
    if (files.length == 0)
59
        return;
60
    else if (files.length == 1)
61
    {
62
        if (file_listing[files[0]].isdir)
63
            conf_msg = "Are you sure you want to delete the directory \""
64
                + files[0] + "\"?\n"
65
                + "All of the files in this directory will be lost.";
66
        else
67
            conf_msg = "Are you sure you want to delete the file \""
68
                + files[0] + "\"?";
69
    }
70
    else
71
    {
72
        var confirm_filelist = "";
73
        var num_dirs = 0;
74
        for (var i=0; i<files.length; i++)
75
        {
76
            if (file_listing[files[i]].isdir)
77
                num_dirs++;
78
            confirm_filelist += "  - " + files[i] + "\n";
79
        }
80
        conf_msg = "Are you sure you want to delete all of the "
81
            + "following ";
82
        if (num_dirs > 0)
83
        {
84
            if (files.length == num_dirs)
85
                conf_msg += "directories";
86
            else
87
                conf_msg += "files and directories";
88
        }
89
        else
90
            conf_msg += "files";
91
        conf_msg += ":\n" + confirm_filelist;
92
        if (num_dirs > 0)
93
            conf_msg += "\nAll of the files in these directories "
94
                     + "will be lost.";
95
    }
96
    /* Now we have the conf message */
97
98
    var confirmed = confirm(conf_msg);
99
    if (!confirmed) return;
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
100
    do_action("delete", current_path, {"path":files});
215 by mattgiuca
listing.js:
101
    return false;
102
}
103
592 by mattgiuca
fileservice, browser/listing: Added new fileservice action, "mkdir".
104
function action_mkdir()
105
{
106
    var path = prompt("New directory name?");
107
    if (path == null) return;
108
    do_action("mkdir", current_path, {"path":path});
109
    return false;
110
}
111
611 by mattgiuca
"New File" now works. (This is a MUCH better replacement for having to go to
112
function action_newfile()
113
{
114
    var path = prompt("New file name?");
115
    if (path == null) return;
116
    /* "Upload" a blank file */
787 by mattgiuca
fileservice_lib/action.py:
117
    /* Note: "overwrite" defaults to false, so will error if it already
118
     * exists. */
611 by mattgiuca
"New File" now works. (This is a MUCH better replacement for having to go to
119
    do_action("putfile", current_path, {"path":path, "data":""});
120
    return false;
121
}
122
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
123
/* Mode is either "copy" or "move".
124
 */
125
function action_copy_or_cut(files, mode)
126
{
127
    /* Store the "clipboard" in the browser cookie */
128
    var clip_obj = {"src": current_path, "file": files, "mode": mode};
129
    write_cookie("clipboard", clip_obj);
130
}
131
215 by mattgiuca
listing.js:
132
function action_copy(files)
133
{
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
134
    action_copy_or_cut(files, "copy");
215 by mattgiuca
listing.js:
135
    return false;
136
}
137
138
function action_cut(files)
139
{
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
140
    action_copy_or_cut(files, "move");
215 by mattgiuca
listing.js:
141
    return false;
142
}
143
144
function action_paste()
145
{
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
146
    /* Get the "clipboard" object from the browser cookie */
147
    var clip_obj = read_cookie("clipboard");
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
148
    var under_subversion;
149
    
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
150
    if (clip_obj == null)
151
    {
152
        alert("No files have been cut or copied.");
153
        return false;
154
    }
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
155
156
    if (clip_obj.mode == "svnmove" || clip_obj.mode == "svncopy")
157
    {
158
        under_subversion = ("svnstatus" in current_file) && 
159
                                (current_file.svnstatus != "unversioned");
160
        if (!under_subversion)
161
        {
162
            alert("Cannot perform an Subversion Move outside of"
163
                                                + " Permanent directories!");
164
            return false;
165
        }        
166
    }
167
    
653 by mattgiuca
browser/listing: Rewrote cut/copy/paste actions to conform to the
168
    /* The clip_obj is exactly what we want to pass, plus the current path
169
     * as destination. */
170
    clip_obj.dst = ".";
171
    do_action("paste", current_path, clip_obj);
215 by mattgiuca
listing.js:
172
    return false;
173
}
174
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
175
function action_svncopy(files)
176
{
177
    action_copy_or_cut(files, "svncopy");
178
    return false;
179
}
180
181
function action_svncut(files)
182
{
183
    action_copy_or_cut(files, "svnmove");
184
    return false;
185
}
186
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
187
function action_add(files)
188
{
189
    do_action("svnadd", current_path, {"path":files});
190
    return false;
191
}
192
921 by wagrant
fileservice_lib, browser: Rename the old remove action to delete, to
193
function action_remove(files)
194
{
195
    do_action("svnremove", current_path, {"path":files});
196
    return false;
197
}
198
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
199
function action_revert(files)
200
{
201
    do_action("svnrevert", current_path, {"path":files});
202
    return false;
203
}
204
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
205
function action_publish(files)
206
{
726 by dcoles
Browser: Added code to allow directories to be published through the UI. Also
207
    do_action("publish", current_path, {"path":files});
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
208
    return false;
209
}
210
211
function action_unpublish(files)
212
{
727 by dcoles
Browser: Added UI code to let you publish and unpublish folders
213
    do_action("unpublish", current_path, {"path":files});
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
214
    return false;
215
}
216
918 by wagrant
browser: Expose svn update functionality. This brings a need for an
217
function action_update(files)
218
{
219
    if (files.length == 0) files = ".";
220
    do_action("svnupdate", current_path, {"path": files});
221
    return false;
222
}
223
919 by wagrant
fileservice_lib: Implement "svn resolved".
224
function action_resolved(files)
225
{
226
    if (files.length == 0) files = ".";
227
    do_action("svnresolved", current_path, {"path": files});
228
    return false;
229
}
230
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
231
function action_commit(files)
232
{
233
    /* Get a commit log from the user */
234
    var logmsg = prompt("Enter commit log:");
223 by mattgiuca
util.js: Added "urlencode_path" which is specially designed to encode paths.
235
    if (logmsg == null) return;
219 by mattgiuca
Browser.js: Added handlers for subversion actions.
236
    do_action("svncommit", current_path, {"path":files, "logmsg": logmsg});
237
    return false;
238
}
239
613 by mattgiuca
browser/listing.js: Added action_selectall which can either select all or
240
/** Selects or deselects all files in the listing.
241
 * selected: true or false (defaults to true).
242
 * If false, deselects instead of selecting.
243
 */
244
function action_selectall(selected)
245
{
246
    if (selected == null)
247
        selected = true;
248
    /* Iterate through and check all the boxes.
249
     * Then update.
250
     * (We do this through the DOM because that is the authority that
251
     * update_selection uses to identify what is selected).
252
     */
253
    var files_children = document.getElementById("files").childNodes;
254
    for (var i=0; i<files_children.length; i++)
255
    {
256
        tr = files_children[i];
257
        tr.firstChild.firstChild.checked = selected;
258
    }
259
    update_selection();
260
}
261
387 by mattgiuca
Implemented file uploads.
262
/* Shows or hides the "upload panel" in the side panel.
263
 * toshow is true for showing, false for hiding.
264
 */
388 by mattgiuca
browser/listing: Upload button now toggles the upload panel instead of just
265
uploadpanel_shown = false;
387 by mattgiuca
Implemented file uploads.
266
function show_uploadpanel(toshow)
267
{
388 by mattgiuca
browser/listing: Upload button now toggles the upload panel instead of just
268
    if (toshow == null)
269
        uploadpanel_shown = !uploadpanel_shown;
270
    else
271
        uploadpanel_shown = toshow;
387 by mattgiuca
Implemented file uploads.
272
    document.getElementById("uploadpanel").setAttribute("style",
388 by mattgiuca
browser/listing: Upload button now toggles the upload panel instead of just
273
        "display: " + (uploadpanel_shown ? "auto" : "none") + ";");
387 by mattgiuca
Implemented file uploads.
274
    return false;
275
}
276
215 by mattgiuca
listing.js:
277
/** END ACTIONS **/
278
597 by mattgiuca
Major refactor of actions in File browser.
279
/** Updates the side-panel AND the actions in the top-bar. Expects selected_files
280
 * reflects the current selected files.
211 by mattgiuca
fileservice/listing: Slight change to date format.
281
 */
282
function update_sidepanel(total_file_size_sel)
283
{
284
    var sidepanel = document.getElementById("sidepanel");
285
    var filename;
286
    var file;
287
    var p;
387 by mattgiuca
Implemented file uploads.
288
    var div;
211 by mattgiuca
fileservice/listing: Slight change to date format.
289
    /* Is this dir under svn? */
602 by mattgiuca
util.js: Added shallow_copy_object function.
290
    var under_subversion = "svnstatus" in current_file;
211 by mattgiuca
fileservice/listing: Slight change to date format.
291
    dom_removechildren(sidepanel);
292
    if (selected_files.length <= 1)
293
    {
294
        if (selected_files.length == 0)
295
        {
296
            /* Display information about the current directory instead */
297
            filename = path_basename(current_path);
602 by mattgiuca
util.js: Added shallow_copy_object function.
298
            file = current_file;
211 by mattgiuca
fileservice/listing: Slight change to date format.
299
        }
300
        else if (selected_files.length == 1)
301
        {
215 by mattgiuca
listing.js:
302
            filename = selected_files[0];
211 by mattgiuca
fileservice/listing: Slight change to date format.
303
            file = file_listing[filename];
304
        }
305
        var filetype;
306
        if ("isdir" in file && file.isdir)
307
            filetype = "text/directory";
308
        else if ("type" in file)
309
            filetype = file.type;
310
        else
311
            filetype = "text/plain";
312
213 by mattgiuca
Fileservice / Files (Python and JS files):
313
        if ("type_nice" in file)
314
            filetype_nice = file.type_nice;
315
        else
316
            filetype_nice = "File";
317
211 by mattgiuca
fileservice/listing: Slight change to date format.
318
        p = document.createElement("p");
319
        sidepanel.appendChild(p);
320
        p.appendChild(dom_make_img(mime_type_to_icon(filetype, true),
321
            null, null, filetype));
322
        p = dom_make_text_elem("h2", filename);
323
        sidepanel.appendChild(p);
213 by mattgiuca
Fileservice / Files (Python and JS files):
324
        p = dom_make_text_elem("p", filetype_nice);
211 by mattgiuca
fileservice/listing: Slight change to date format.
325
        sidepanel.appendChild(p);
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
326
        var mini_icons = document.createElement("p");
327
        sidepanel.appendChild(mini_icons);
328
        var icon;
213 by mattgiuca
Fileservice / Files (Python and JS files):
329
        if (under_subversion)
330
        {
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
331
            icon = svnstatus_to_icon(file.svnstatus);
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
332
            if (icon)
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
333
                mini_icons.appendChild(dom_make_img(icon, icon_size, icon_size,
230 by mattgiuca
Removed "unversioned" icon from subversion status. Now unversioned files do
334
                    svnstatus_to_string(file.svnstatus)));
213 by mattgiuca
Fileservice / Files (Python and JS files):
335
            p = dom_make_text_elem("p", svnstatus_to_string(file.svnstatus));
336
            sidepanel.appendChild(p);
337
        }
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
338
        if ("published" in file && file.published)
339
        {
340
            icon = make_path(path_join(published_icon));
341
            if (icon)
342
            {
343
                if (mini_icons.childNodes.length > 0)
344
                    mini_icons.appendChild(document.createTextNode(" "));
345
                mini_icons.appendChild(dom_make_img(icon, icon_size, icon_size,
327 by mattgiuca
browser: Renamed "Published directory" label to "Published to the web".
346
                    "Published to the web"));
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
347
            }
327 by mattgiuca
browser: Renamed "Published directory" label to "Published to the web".
348
            p = dom_make_text_elem("p", "Published to the web");
269 by mattgiuca
browser: Added publish functionality to JavaScript client side.
349
            p.setAttribute("title",
350
                "Anybody on the web can view the files in this directory.");
351
            sidepanel.appendChild(p);
352
        }
353
        /* If we never wrote any mini-icons, remove this element */
354
        if (mini_icons.childNodes.length == 0)
355
            sidepanel.removeChild(mini_icons);
211 by mattgiuca
fileservice/listing: Slight change to date format.
356
        if ("size" in file)
357
        {
358
            p = dom_make_text_elem("p", "Size: " + nice_filesize(file.size));
359
            sidepanel.appendChild(p);
360
        }
361
        if ("mtime_nice" in file)
362
        {
608 by mattgiuca
browser/listing: REMOVED the generation of all action links to the right
363
            /* Break into lines on comma (separating date from time) */
364
            filetime_lines = file.mtime_nice.split(",");
365
            p = document.createElement("p");
366
            p.appendChild(document.createTextNode("Modified:"));
367
            for (var i=0; i<filetime_lines.length; i++)
368
            {
369
                p.appendChild(document.createElement("br"));
370
                p.appendChild(document.createTextNode(filetime_lines[i]));
371
            }
211 by mattgiuca
fileservice/listing: Slight change to date format.
372
            sidepanel.appendChild(p);
373
        }
374
    }
375
    else
376
    {
377
        /* Multiple files selected */
378
        p = document.createElement("p");
379
        sidepanel.appendChild(p);
380
        p.appendChild(dom_make_img(
224 by mattgiuca
util.js: Removed urlencoding support from "encoded_app_path" (now called
381
            app_path(type_icons_path_large, "multi.png"),
211 by mattgiuca
fileservice/listing: Slight change to date format.
382
            null, null, "Multiple files"));
383
        p = dom_make_text_elem("h2",
384
            selected_files.length.toString() + " files selected");
385
        sidepanel.appendChild(p);
386
        p = dom_make_text_elem("p", "Total size: "
387
            + nice_filesize(total_file_size_sel));
388
        sidepanel.appendChild(p);
389
    }
390
}
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
391
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
392
/** Updates the side-panel and status bar to reflect the current set of
393
 * selected files. This is done by inspecting the states of the check boxes.
394
 * Also changes the styling to highlight selected files.
395
 */
396
function update_selection()
397
{
398
    /* First get a list of all files that are selected, and
399
     * reset the styling on each file's row. */
400
    var files_children = document.getElementById("files").childNodes;
401
    var tr;
402
    var checkbox;
403
    var row_toggle = 1;
404
    selected_files = [];  /* Clear global selected_files */
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
405
406
    var total_file_size = 0;    /* In bytes */
407
    var total_file_size_sel = 0;
408
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
409
    /* Children are trs */
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
410
    var filename;
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
411
    var file;
412
    if (file_listing == null) return;
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
413
    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
414
    {
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
415
        filename = files_children[i].filename;
416
        file = files_children[i].fileinfo;
417
        /* 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
418
         */
419
        if ("size" in file)
420
            total_file_size += file.size;
421
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
422
        tr = files_children[i];
423
        checked = tr.firstChild.firstChild.checked;
424
        /* Set the class for every row based on both the checked state,
425
         * and whether it is odd or even */
426
        tr.setAttribute("class", "row" + row_toggle.toString() +
427
            (checked ? "sel" : ""))
428
        row_toggle = row_toggle == 1 ? 2 : 1;
429
        if (checked)
430
        {
431
            /* Add the filename (column 3) to the selected_files list */
432
            selected_files[selected_files.length] = filename;
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
433
            if ("size" in file)
434
                total_file_size_sel += file.size;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
435
        }
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
436
    }
437
597 by mattgiuca
Major refactor of actions in File browser.
438
    /* Write to the side-panel and actions bar */
439
    update_actions();
211 by mattgiuca
fileservice/listing: Slight change to date format.
440
    update_sidepanel(total_file_size_sel);
441
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
442
    /* Write to the status bar */
443
    var statusbar = document.getElementById("statusbar");
444
    var statusmsg;
445
    var file_plural;
446
    if (selected_files.length > 0)
447
    {
448
        statusmsg = selected_files.length.toString() + " file"
449
            + (selected_files.length == 1 ? "" : "s") + " selected, "
450
            + nice_filesize(total_file_size_sel);
451
    }
452
    else
453
    {
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
454
        statusmsg = files_children.length.toString() + " file"
455
            + (files_children.length == 1 ? "" : "s") + ", "
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
456
            + nice_filesize(total_file_size);
457
    }
458
    dom_removechildren(statusbar);
459
    statusbar.appendChild(document.createTextNode(statusmsg));
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
460
}
461
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
462
/** SORTING FUNCTIONS **/
463
464
/** Sorts the file table. Physically manipulates the DOM table to reflect the
465
 * sorted nodes, and also updates the little sort arrow.
466
 *
467
 * \param sort_field The name of the field to sort on primarily. This can
468
 * either be "filename", or one of the fields of a fileinfo object. Note that
469
 * while this determines the primary sort key, the secondary sort keys are
470
 * determined by the global sort_order. Calling sort_listing reorders
471
 * sort_order, bringing the specified sort_field to the top.
472
 * Also note that sorting by "isdir" is more prominent than whatever field is
473
 * provided here.
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
474
 * \param ascending If true, sorts ascending. If false, descending.
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
475
 */
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
476
function sort_listing(sort_field, ascending)
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
477
{
478
    var i;
479
    var files = document.getElementById("files");
480
    var files_children = files.childNodes;
481
    var files_array = new Array(files_children.length);
482
    /* Update sort_order, bringing sort_field to the top. */
557 by agdimech
/browser/listing.js: Fixed ascending/descending functionality when clicked.
483
    if(sort_order[sort_order.length-1] == sort_field)
484
    {
485
        sort_ascending = ascending != false ? true : false;
486
    }
487
    else
488
    {
489
        sort_ascending = true;
490
        sort_order.removeall(sort_field);
491
        sort_order.push(sort_field);
492
    }
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
493
494
    /* Build an array of DOM tr elements (with the additional 'filename' and
495
     * 'fileinfo' attributes as written when the listing is created). */
496
    /* Note: Must manually create an array from files_children, which is a DOM
497
     * NodeList, not an array. */
498
    for (i=0; i<files_children.length; i++)
499
        files_array[i] = files_children[i];
500
501
    /* Sort this array */
502
    files_array.sort(compare_files);
503
504
    /* Clean out the table (the TRs are safely stored in the array) */
505
    dom_removechildren(files);
506
507
    /* Insert the TRs back into the table, in their sorted order */
508
    for (i=0; i<files_array.length; i++)
509
        files.appendChild(files_array[i]);
510
511
    /* Fix the coloring classes on the rows so they are interleaved. */
512
    update_selection();
513
514
    return false;
515
}
516
517
/** Comparison function used for sorting. Compares two DOM tr nodes (with
518
 * the additional 'filename' and 'fileinfo' attributes as written when the
519
 * listing is created).
520
 * Returns an integer, which is -1 if a < b, 0 if a == b, and 1 if a > b.
521
 * The fields to compare by are determined by the global variable sort_order.
522
 */
523
function compare_files(a, b)
524
{
236 by mattgiuca
listing.js: Correct sorting by directory. (Now sorts all directories to the
525
    /* First sort by whether or not it is a directory */
526
    var aisdir = a.fileinfo.isdir == true;
527
    var bisdir = b.fileinfo.isdir == true;
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
528
    var LESS = sort_ascending == true ? -1 : 1;
529
    var GREATER = -LESS;
530
    if (aisdir > bisdir) return LESS;
531
    else if (aisdir < bisdir) return GREATER;
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
532
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
533
    /* Reverse order of sort_order. (top is highest priority) */
534
    for (var i=sort_order.length-1; i>=0; i--)
535
    {
536
        var field = sort_order[i];
537
        if (field == "filename")
538
        {
539
            if (a.filename < b.filename) return LESS;
540
            else if (a.filename > b.filename) return GREATER;
541
        }
542
        else
543
        {
544
            /* null > anything else (so it appears at the bottom) */
543 by agdimech
browser/listing.js: Fixed sorting for date and size by adding .fileinfo
545
            if (!(field in a.fileinfo))
555 by agdimech
browser/listing.js: Fixed priority queue for sorting due to layout issues.
546
            {
547
                if (field in b.fileinfo)
548
                    return GREATER;
549
                else
550
                    break;
551
            }
543 by agdimech
browser/listing.js: Fixed sorting for date and size by adding .fileinfo
552
            if (!(field in b.fileinfo)) return LESS;
240 by mattgiuca
browser/listing.js: Wrote real comparison function and set up sort_order array
553
            if (a.fileinfo[field] < b.fileinfo[field]) return LESS;
554
            else if (a.fileinfo[field] > b.fileinfo[field]) return GREATER;
555
        }
556
    }
235 by mattgiuca
listing.js: Added sorting functions and a bit of infrastructure to facilitate
557
558
    return 0;
559
}
560
561
/** END SORTING **/
562
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
563
/** Initialises the DOM elements required to present files window,
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
564
 * assuming that clear_page has just been called or the page just
565
 * loaded for the first time.
566
 */
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
567
function setup_for_listing()
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
568
{
569
    var filesbody = document.getElementById("filesbody");
570
381 by mattgiuca
media/browser/listing.js: Replaced table-based layout in file listing with
571
    /* There are 2 divs in the filesbody: middle and statusbar
572
     * middle has 2 divs: filetable, sidepanel
573
     */
574
    /* Middle */
575
    var middle = document.createElement("div");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
576
    filesbody.appendChild(middle);
577
    middle.setAttribute("id", "middle");
381 by mattgiuca
media/browser/listing.js: Replaced table-based layout in file listing with
578
    /* File table */
579
    var filetable = document.createElement("div");
580
    middle.appendChild(filetable);
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
581
    filetable.setAttribute("id", "filetable");
582
    var filetablediv = document.createElement("div");
583
    filetable.appendChild(filetablediv);
584
    filetablediv.setAttribute("id", "filetablediv");
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
585
586
    /* Side-panel */
587
    /* 2 nested divs, so we can set the width exactly and have padding inside
588
     * of that */
589
    var sidepanel_outer = document.createElement("div");
590
    middle.appendChild(sidepanel_outer);
591
    sidepanel_outer.setAttribute("id", "sidepanel_outer");
592
    var sidepanel = document.createElement("div");
593
    sidepanel_outer.appendChild(sidepanel);
594
    sidepanel.setAttribute("id", "sidepanel");
595
596
    /* Now after the table "middle", there is a status bar */
597
    var statusbar_outer = document.createElement("div");
598
    filesbody.appendChild(statusbar_outer);
599
    statusbar_outer.setAttribute("id", "statusbar_outer");
600
    var statusbar = document.createElement("div");
601
    statusbar_outer.appendChild(statusbar);
602
    statusbar.setAttribute("id", "statusbar");
603
}
604
605
/** Sets up the DOM elements required to present a directory liisting.
606
 */
607
function setup_dir_listing()
608
{
609
    var filesbody = document.getElementById("filesbody");
610
    var filetable = document.getElementById("filetable");
611
    var filetablediv = document.getElementById("filetablediv");
612
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
613
    /* A nested table within this div - the actual files listing */
614
    var filetabletable = document.createElement("table");
615
    filetablediv.appendChild(filetabletable);
616
    filetabletable.setAttribute("width", "100%");
617
    var filetablethead = document.createElement("thead");
618
    filetabletable.appendChild(filetablethead);
619
    var filetablethead_tr = document.createElement("tr");
620
    filetablethead.appendChild(filetablethead_tr);
621
    filetablethead_tr.setAttribute("class", "rowhead");
622
    /* Row headers */
623
    var filetablethead_th = document.createElement("th");
624
    filetablethead_tr.appendChild(filetablethead_th);
625
    filetablethead_th.setAttribute("class", "col-check");
626
    filetablethead_th = dom_make_link_elem("th", "Filename",
545 by agdimech
browser/listing.js: Fixed part of the ascending/descending sort however it doesnt take into account changes in primary key.
627
        "Sort by filename", null,
628
	"return sort_listing(\"filename\", !sort_ascending)");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
629
    filetablethead_tr.appendChild(filetablethead_th);
630
    filetablethead_th.setAttribute("class", "col-filename");
631
    filetablethead_th.setAttribute("colspan", 3);
632
    filetablethead_th = dom_make_link_elem("th", "Size",
545 by agdimech
browser/listing.js: Fixed part of the ascending/descending sort however it doesnt take into account changes in primary key.
633
        "Sort by file size", null, "return sort_listing(\"size\",!sort_ascending)");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
634
    filetablethead_tr.appendChild(filetablethead_th);
635
    filetablethead_th.setAttribute("class", "col-size");
636
    filetablethead_th = dom_make_link_elem("th", "Modified",
545 by agdimech
browser/listing.js: Fixed part of the ascending/descending sort however it doesnt take into account changes in primary key.
637
        "Sort by date modified", null, "return sort_listing(\"mtime\",!sort_ascending)");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
638
    filetablethead_tr.appendChild(filetablethead_th);
639
    filetablethead_th.setAttribute("class", "col-date");
640
    /* Empty body */
641
    var filetabletbody = document.createElement("tbody");
642
    filetabletable.appendChild(filetabletbody);
643
    filetabletbody.setAttribute("id", "files");
644
}
645
646
/** Presents the directory listing.
647
 */
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
648
function handle_dir_listing(path, listing)
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
649
{
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
650
    /* Add the DOM elements for the file listing */
651
    setup_dir_listing()
652
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
653
    var row_toggle = 1;
980 by dcoles
Files: "Junk" is now only shown when other (non-subject/stuff) files are in the
654
    
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
655
    /* Is this dir under svn? */
944 by dcoles
Special Home Directory: Work to create a special home directory that shows the
656
    var under_subversion = ("svnstatus" in current_file) && (current_file.svnstatus != "unversioned");
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
657
658
    var files = document.getElementById("files");
659
    var file;
660
    var row;
661
    var td;
662
    var checkbox;
663
386 by mattgiuca
browser/listing: Fixed long-standing bug, files get deselected when you
664
    /* Convert selected_files array into a dictionary which can be efficiently
665
     * searched. */
666
    sel_files_dict = {};
667
    for (var i=0; i<selected_files.length; i++)
668
    {
669
        sel_files_dict[selected_files[i]] = true;
670
    }
671
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
672
    /* Create all of the files */
673
    for (var filename in listing)
674
    {
1060 by wagrant
Make IVLE work fine in Firefox 3.1 (ie. Gecko/XULRunner 1.9.1). Gecko 1.9.1 has
675
        select_row = function() {
676
            var files_children = document.getElementById("files").childNodes;
677
            var checkbox;
678
            var tr;
679
            for (var i=0; i<files_children.length; i++)
680
            {
681
                tr = files_children[i];
682
                checkbox = tr.firstChild.firstChild;
683
                checkbox.checked = tr == this.parentNode;
684
            }
685
            update_selection();
686
        }
687
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
688
        file = listing[filename];
234 by mattgiuca
browser/listing.js:
689
        /* Make a 'tr' element. Store the filename and fileinfo in
690
         * here. */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
691
        row = document.createElement("tr");
234 by mattgiuca
browser/listing.js:
692
        row.filename = filename;
693
        row.fileinfo = file;
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
694
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
695
        /* Column 1: Selection checkbox */
696
        row.setAttribute("class", "row" + row_toggle.toString())
697
        row_toggle = row_toggle == 1 ? 2 : 1;
698
        td = document.createElement("td");
699
        checkbox = document.createElement("input");
700
        checkbox.setAttribute("type", "checkbox");
701
        checkbox.setAttribute("title", "Select this file");
702
        checkbox.setAttribute("onchange", "update_selection()");
386 by mattgiuca
browser/listing: Fixed long-standing bug, files get deselected when you
703
        /* Check the box if selected_files says it's selected */
704
        checkbox.checked = filename in sel_files_dict;
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
705
        td.appendChild(checkbox);
706
        row.appendChild(td);
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
707
708
        /* Column 2: Filetype and subversion icons. */
709
        td = document.createElement("td");
710
        td.setAttribute("class", "thincol");
1060 by wagrant
Make IVLE work fine in Firefox 3.1 (ie. Gecko/XULRunner 1.9.1). Gecko 1.9.1 has
711
        td.addEventListener("click", select_row, false);
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
712
        /* Directories don't really have a MIME type, so we fake one. */
713
        if (file.isdir) file.type = "text/directory";
714
        td.appendChild(dom_make_img(mime_type_to_icon(file.type),
715
            icon_size, icon_size, file.type_nice));
716
        row.appendChild(td);
717
        td = document.createElement("td");
718
        td.setAttribute("class", "thincol");
1086 by chadnickbok
This commit fixes issue #10 and part of issue #9
719
        var icon = svnstatus_to_icon(file.svnstatus);
720
        if (icon)
721
            td.appendChild(dom_make_img(icon, icon_size, icon_size,
722
                                        svnstatus_to_string(file.svnstatus)));
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
723
        row.appendChild(td);
724
725
        /* Column 3: Filename */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
726
        if (file.isdir)
727
        {
728
            td = dom_make_link_elem("td", filename,
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
729
                 "Navigate to " + path_join(path, filename),
910 by wagrant
filebrowser_lib: Send the current revision along with the listing if we
730
                 build_revision_url(path, filename, current_revision),
731
                 null, true);
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
732
        }
733
        else
734
        {
735
            td = dom_make_text_elem("td", filename);
736
        }
1060 by wagrant
Make IVLE work fine in Firefox 3.1 (ie. Gecko/XULRunner 1.9.1). Gecko 1.9.1 has
737
        td.addEventListener("click", select_row, false);
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
738
        row.appendChild(td);
739
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
740
        /* Column 4: Size */
741
        td = dom_make_text_elem("td", nice_filesize(file.size));
1060 by wagrant
Make IVLE work fine in Firefox 3.1 (ie. Gecko/XULRunner 1.9.1). Gecko 1.9.1 has
742
        td.addEventListener("click", select_row, false);
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
743
        row.appendChild(td);
909 by wagrant
listing.js: Remove duplication in get_dir_listing's row generation.
744
745
        /* Column 5: Date */
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
746
        td = dom_make_text_elem("td", file.mtime_short, file.mtime_nice);
1060 by wagrant
Make IVLE work fine in Firefox 3.1 (ie. Gecko/XULRunner 1.9.1). Gecko 1.9.1 has
747
        td.addEventListener("click", select_row, false);
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
748
        row.appendChild(td);
749
        files.appendChild(row);
750
    }
751
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
752
    /* Apply an initial sort by filename */
753
    sort_listing("filename");
754
210 by mattgiuca
File browser: listing.js - The status bar is now updated whenever the
755
    /* Do a selection update (create initial elements for side panel and
756
     * status bar). */
237 by mattgiuca
listing: bugfix, update_selection no longer dependent on dictionary ordering
757
    /* Commented out; already called by sort_listing */
758
    /*update_selection();*/
209 by mattgiuca
browser.js: Split out dir-listing code into listing.js (it's going to get
759
}
760