-
Notifications
You must be signed in to change notification settings - Fork 157
/
expand_dir.js
167 lines (150 loc) · 6.17 KB
/
expand_dir.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Enable expanding/folding folders in TracBrowser
(function($){
var FOLDERID_COUNTER = 0;
var SUBFOLDER_INDENT = 20;
// enableExpandDir adds the capability to ''folder'' rows in a table
// to be expanded and folded.
//
// It also teach the rows about their ancestors. It expects:
// - `parent_tr`, the logical parent row (`null` if there's no ancestor)
// - a `rows` jQuery object matching the newly created entry rows
// - `qargs`, additional parameters to send to the server when expanding
// - `autoexpand`, an optional array corresponding to a splitted sub-path
// of entries that will be expanded automatically.
window.enableExpandDir = function(parent_tr, rows, qargs, autoexpand) {
// the ancestors folder ids are present in the parent_tr class attribute
var ancestor_folderids = [];
if (parent_tr) // rows are logical children of the parent_tr row
ancestor_folderids = $.grep(parent_tr.attr("class").split(" "),
function(c) { return c.match(/^f\d+$/)});
else { // rows are toplevel rows, this is the initial call
var anchor = window.location.hash.substr(1);
if (anchor)
autoexpand = decodeURI(anchor).split("/");
}
var autoexpand_expander = null;
rows.each(function () {
var a = $(this).find("a.dir");
if (a.length) { // then the entry is a folder
// create new folder id
var folderid = "f" + FOLDERID_COUNTER++;
this.id = folderid;
$(this).addClass(folderid);
// add the expander icon
var expander = $('<span class="expander"> </span>')
.attr("title", _("Expand sub-directory in place"))
.click(function() { toggleDir($(this), qargs); })
a.before(expander);
if (autoexpand && a.text() == autoexpand[0])
autoexpand_expander = expander;
}
// tie that row to ancestor folders
if (parent_tr)
$(this).addClass(ancestor_folderids.join(" "));
});
if ( autoexpand_expander )
toggleDir(autoexpand_expander, qargs, autoexpand.slice(1));
}
// handler for click event on the expander icons
window.toggleDir = function(expander, qargs, autoexpand) {
var tr = expander.parents("tr:first");
var folderid = tr.get(0).id;
if ( tr.hasClass("expanded") ) { // then *fold*
tr.removeClass("expanded");
if (tr.next().hasClass("error")) {
tr.next().remove();
} else {
tr.addClass("collapsed");
tr.siblings("tr."+folderid).hide();
}
expander.attr("title", _("Re-expand directory"));
return;
}
// update location, unless autoexpand in progress
var a = expander.next("a");
if ( !autoexpand ) {
var pathname = window.location.pathname;
// strip scheme and hostname, href is absolute with IE 6 and 7.
var entry_href = a.attr("href").replace(/^[^:]+:\/\/[^\/]+/, '');
// normalize (PATH_INFO possibly has squashed "/")
pathname = pathname.replace(/\/+/g, '/').replace(/\/$/, '');
entry_href = entry_href.replace(/\/+/g, '/');
window.location.hash = entry_href.substr(pathname.length + 1)
.replace(/([^?]*)(\?.*)?$/, '$1');
}
// update sort links in column headers
tr.parents("table:first").find("thead tr:first").find("a").each(function(){
var href = $(this).attr("href").replace(/#.*$/, '');
$(this).attr("href", href+window.location.hash);
});
if ( tr.hasClass("collapsed") ) { // then *expand*
tr.removeClass("collapsed").addClass("expanded");
tr.siblings("tr."+folderid).show();
// Note that the above will show all the already fetched subtrees,
// so we have to fold again the folders which were already collapsed.
tr.siblings("tr.collapsed").each(function() {
tr.siblings("tr."+this.id).not(this).hide();
});
} else { // then *fetch*
var td = expander.parents("td:first");
var td_class = td.attr("class");
var depth =
parseFloat(td.css("padding-left").replace(/^(\d*\.\d*).*$/, "$1")) +
SUBFOLDER_INDENT;
tr.addClass("expanded");
// insert "Loading ..." row
var loading_row = $($.htmlFormat(
'<tr>' +
' <td class="$td_class" colspan="$colspan" ' +
' style="padding-left: ${depth}px">' +
' <span class="loading">${loading}</span>' +
' </td>' +
'</tr>', {
td_class: td_class,
colspan: tr.children("td").length,
depth: depth,
loading: babel.format(_("Loading %(entry)s..."), {entry: a.text()})
}));
tr.after(loading_row);
// XHR for getting the rows corresponding to the folder entries
$.ajax({
type: "GET",
url: a.attr("href"),
data: qargs,
dataType: "html",
success: function(data) {
// Safari 3.1.1 has some trouble reconstructing HTML snippets
// bigger than 50k - splitting in rows before building DOM nodes
var rows = data.replace(/^<!DOCTYPE[^>]+>/, "").split("</tr>");
if (rows.length) {
// insert entry rows
$(rows).each(function() {
row = $(this+"</tr>");
row.children("td."+td_class).css("padding-left", depth);
// make all entry rows collapsible but only subdir rows expandable
loading_row.before(row);
enableExpandDir(tr, row, qargs, autoexpand);
});
// remove "Loading ..." row
loading_row.remove();
} else {
loading_row.find("span.loading")
.text("")
.append("<i>" + _("(empty)") + "</i>")
.removeClass("loading");
enableExpandDir(tr, loading_row, qargs); // make it collapsible
}
},
error: function(req, err, exc) {
loading_row.find("span.loading")
.text("")
.append("<i>" + _("(error)") + "</i>")
.removeClass("loading");
loading_row.addClass("error");
enableExpandDir(tr, loading_row, qargs); // make it collapsible
}
});
}
expander.attr("title", _("Fold directory"));
}
})(jQuery);