hfs 0.1.6 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +674 -0
- package/README.md +102 -8
- package/admin/assets/index.dcc78777.css +1 -0
- package/admin/assets/index.f056db34.js +282 -0
- package/admin/assets/sha512.3c0e384c.js +8 -0
- package/admin/index.html +17 -0
- package/admin/logo.svg +36 -0
- package/frontend/assets/index.55c710c2.js +85 -0
- package/frontend/assets/index.ee805a6c.css +1 -0
- package/frontend/assets/sha512.634b743e.js +8 -0
- package/frontend/fontello.css +77 -0
- package/frontend/fontello.woff2 +0 -0
- package/frontend/index.html +18 -0
- package/package.json +93 -28
- package/plugins/antibrute/plugin.js +38 -0
- package/plugins/download-counter/plugin.js +47 -0
- package/plugins/download-counter/public/hits.js +5 -0
- package/plugins/updater-disabled/plugin.js +44 -0
- package/plugins/vhosting/plugin.js +42 -0
- package/src/QuickZipStream.js +285 -0
- package/src/ThrottledStream.js +93 -0
- package/src/adminApis.js +169 -0
- package/src/api.accounts.js +59 -0
- package/src/api.auth.js +130 -0
- package/src/api.file_list.js +103 -0
- package/src/api.helpers.js +32 -0
- package/src/api.monitor.js +102 -0
- package/src/api.plugins.js +125 -0
- package/src/api.vfs.js +164 -0
- package/src/apiMiddleware.js +136 -0
- package/src/block.js +33 -0
- package/src/commands.js +105 -0
- package/src/config.js +172 -0
- package/src/connections.js +57 -0
- package/src/const.js +83 -0
- package/src/crypt.js +21 -0
- package/src/debounceAsync.js +48 -0
- package/src/events.js +9 -0
- package/src/frontEndApis.js +38 -0
- package/src/github.js +102 -0
- package/src/index.js +53 -0
- package/src/listen.js +226 -0
- package/src/log.js +137 -0
- package/src/middlewares.js +154 -0
- package/src/misc.js +160 -0
- package/src/pbkdf2.js +74 -0
- package/src/perm.js +176 -0
- package/src/plugins.js +338 -0
- package/src/serveFile.js +104 -0
- package/src/serveGuiFiles.js +113 -0
- package/src/sse.js +29 -0
- package/src/throttler.js +91 -0
- package/src/update.js +69 -0
- package/src/util-files.js +141 -0
- package/src/util-generators.js +30 -0
- package/src/util-http.js +30 -0
- package/src/vfs.js +227 -0
- package/src/watchLoad.js +73 -0
- package/src/zip.js +69 -0
- package/.npmignore +0 -19
- package/admin-server.js +0 -212
- package/cli.js +0 -33
- package/file-server.js +0 -100
- package/lib/common.js +0 -10
- package/lib/extending.js +0 -158
- package/lib/mime.js +0 -19
- package/lib/misc.js +0 -75
- package/lib/serving.js +0 -81
- package/lib/vfs.js +0 -403
- package/main.js +0 -24
- package/note.txt +0 -104
- package/speedtest.js +0 -21
- package/static/backend.css +0 -14
- package/static/backend.html +0 -32
- package/static/backend.js +0 -694
- package/static/extending.js +0 -187
- package/static/frontend.css +0 -29
- package/static/frontend.html +0 -23
- package/static/frontend.js +0 -230
- package/static/icons/files/archive.png +0 -0
- package/static/icons/files/audio.png +0 -0
- package/static/icons/files/file.png +0 -0
- package/static/icons/files/folder.png +0 -0
- package/static/icons/files/image.png +0 -0
- package/static/icons/files/link.png +0 -0
- package/static/icons/files/video.png +0 -0
- package/static/jquery.js +0 -4
- package/static/jquery.rule-1.0.2.js +0 -273
- package/static/misc.js +0 -194
- package/static/tpl.js +0 -17
- package/todo.txt +0 -25
package/static/extending.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
///////// EXTENDING FUNCTION
|
|
2
|
-
|
|
3
|
-
/** as function.bind(), but additional parameters are prepended instead of appended
|
|
4
|
-
* @return {function} proxied function
|
|
5
|
-
*/
|
|
6
|
-
Function.prototype.prebind = function(){
|
|
7
|
-
var args = Array.prototype.slice.call(arguments);
|
|
8
|
-
var scope = args.shift();
|
|
9
|
-
var fun = this;
|
|
10
|
-
return function(){
|
|
11
|
-
var moreArgs = Array.prototype.slice.call(arguments);
|
|
12
|
-
fun.apply(scope, moreArgs.concat(args));
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
if (!Function.prototype.bind)
|
|
17
|
-
Function.prototype.bind = function(){
|
|
18
|
-
var args = Array.prototype.slice.call(arguments);
|
|
19
|
-
var scope = args.shift();
|
|
20
|
-
var fun = this;
|
|
21
|
-
return function(){
|
|
22
|
-
var moreArgs = Array.prototype.slice.call(arguments);
|
|
23
|
-
fun.apply(scope, args.concat(moreArgs));
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
///////// EXTENDING STRING
|
|
28
|
-
|
|
29
|
-
/* return a new string filling "this" with arguments' values.
|
|
30
|
-
The filling is done in place of strings in this form {key} or this other form {key|parameter}.
|
|
31
|
-
If first argument is an object, then "key" is used as field name (i.e. property) of the object.
|
|
32
|
-
Otherwise "key" should be a number, and it's the argument's index (zero-based).
|
|
33
|
-
As stated before, keys can have a parameter. If such parameter is in the form \d*-\d* then these numbers
|
|
34
|
-
denote a range of characters to extract (i.e. a substring). Otherwise the parameter is a property name for
|
|
35
|
-
the value (that must be an object or an array in this case).
|
|
36
|
-
*/
|
|
37
|
-
String.prototype.format = function() {
|
|
38
|
-
var args = arguments;
|
|
39
|
-
if (typeof args[0] == 'object')
|
|
40
|
-
args = args[0];
|
|
41
|
-
return this.replace(/\{([-_ a-z0-9]+)(\|([^}]+))?\}/gi, function(){
|
|
42
|
-
var ret = args[arguments[1]];
|
|
43
|
-
var par = arguments[3];
|
|
44
|
-
if (par) {
|
|
45
|
-
var v = /(\d*)-(\d*)/.exec(par); // is it in the "range" form?
|
|
46
|
-
if (v) ret = ret.substring(v[1]-1 || 0, v[2] || ret.length); // extract the substring in range
|
|
47
|
-
else ret = ret[par]; // get property
|
|
48
|
-
}
|
|
49
|
-
return ret;
|
|
50
|
-
});
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
String.prototype.repeat = function(n) {
|
|
54
|
-
var r = '';
|
|
55
|
-
for (var i=0; i<n; i++) r += this;
|
|
56
|
-
return r;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
String.prototype.count = function(sub) {
|
|
60
|
-
return this.split(sub).length-1;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
String.prototype.ss = function(from, to) {
|
|
64
|
-
return this.substring(from<0 ? this.length-from : from, to<0 ? this.length+to : to);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
String.prototype.pad = function(lngt, filler) {
|
|
68
|
-
return (filler || ' ').repeat(Math.max(0,lngt - this.length)) + this;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
String.prototype.escapeRegExp = function() {
|
|
72
|
-
return this.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
String.prototype.startsBy = function(sub, caseInsensitive) {
|
|
76
|
-
return 0 <= this.search(new RegExp('^'+sub.escapeRegExp(), caseInsensitive ? 'i' : ''));
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
String.prototype.endsBy = function(sub, caseInsensitive) {
|
|
80
|
-
return 0 <= this.search(new RegExp(sub.escapeRegExp()+'$', caseInsensitive ? 'i' : ''));
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
String.prototype.includeLeading = function(sub) { return this.startsBy(sub) ? this : sub+this };
|
|
84
|
-
String.prototype.includeTrailing = function(sub) { return this.endsBy(sub) ? this : this+sub };
|
|
85
|
-
// if in the following function the casting to string is not made, the resulting typeof is 'object' instead of 'string' (causing problems in some cases, e.g. using path.join)
|
|
86
|
-
String.prototype.excludeLeading = function(sub) { return this.startsBy(sub) ? this.slice(sub.length) : ''+this };
|
|
87
|
-
String.prototype.excludeTrailing = function(sub) { return this.endsBy(sub) ? this.slice(0,-sub.length) : ''+this };
|
|
88
|
-
|
|
89
|
-
// handy shortcuts
|
|
90
|
-
String.prototype.low = String.prototype.toLowerCase;
|
|
91
|
-
String.prototype.up = String.prototype.toUpperCase;
|
|
92
|
-
|
|
93
|
-
// case insensitive test
|
|
94
|
-
String.prototype.same = function(s){
|
|
95
|
-
var threshold = 10;
|
|
96
|
-
return typeof s === 'string'
|
|
97
|
-
&& this.length === s.length
|
|
98
|
-
&& this.substr(0,threshold).low() === s.substr(0,threshold).low()
|
|
99
|
-
&& this.substr(threshold).low() === s.substr(threshold).low()
|
|
100
|
-
}; // String.same
|
|
101
|
-
|
|
102
|
-
String.prototype.in = function(s) {
|
|
103
|
-
switch (typeof s) {
|
|
104
|
-
case 'array':
|
|
105
|
-
case 'string': return s.indexOf(this) >= 0;
|
|
106
|
-
default: return false;
|
|
107
|
-
}
|
|
108
|
-
}; // String.in
|
|
109
|
-
|
|
110
|
-
///////// EXTENDING ARRAY
|
|
111
|
-
|
|
112
|
-
if (!Array.prototype.forEach)
|
|
113
|
-
Array.prototype.forEach = function(fun) {
|
|
114
|
-
if (typeof fun != "function")
|
|
115
|
-
throw new TypeError();
|
|
116
|
-
for (var i=0, l=this.length; i<l; ++i) {
|
|
117
|
-
fun.call(this[i], this[i], i, this);
|
|
118
|
-
}
|
|
119
|
-
}; // Array.forEach
|
|
120
|
-
|
|
121
|
-
if (!Array.prototype.some)
|
|
122
|
-
Array.prototype.some = function(cb) {
|
|
123
|
-
for (var i=0, l=this.length; i<l; ++i) {
|
|
124
|
-
if (cb ? cb(this[i]) : this[i]) {
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
}; // Array.some
|
|
130
|
-
|
|
131
|
-
///////// EXTENDING OBJECT
|
|
132
|
-
|
|
133
|
-
function extendObject(key, value) {
|
|
134
|
-
Object.defineProperty(Object.prototype, key, {
|
|
135
|
-
enumerable: false,
|
|
136
|
-
value: value
|
|
137
|
-
});
|
|
138
|
-
} // extendObject
|
|
139
|
-
|
|
140
|
-
extendObject('getKeyOf', function(value) {
|
|
141
|
-
for (var i in this)
|
|
142
|
-
if (this.hasOwnProperty(i)
|
|
143
|
-
&& this[i] === value)
|
|
144
|
-
return i;
|
|
145
|
-
return null;
|
|
146
|
-
}); // Object.getKeyOf
|
|
147
|
-
|
|
148
|
-
extendObject('forEach', function(cb) {
|
|
149
|
-
for (var i in this)
|
|
150
|
-
if (this.hasOwnProperty(i))
|
|
151
|
-
cb(this[i], i);
|
|
152
|
-
}); // Object.forEach
|
|
153
|
-
|
|
154
|
-
extendObject('isIn', function(vals) {
|
|
155
|
-
if (arguments.length == 1) {
|
|
156
|
-
return Array.isArray(vals)
|
|
157
|
-
? vals.indexOf(this) >= 0
|
|
158
|
-
: vals.keyOf(this) !== null;
|
|
159
|
-
}
|
|
160
|
-
for (var i in arguments)
|
|
161
|
-
if (arguments[i] == this)
|
|
162
|
-
return true;
|
|
163
|
-
return false;
|
|
164
|
-
}); // Object.isIn
|
|
165
|
-
|
|
166
|
-
extendObject('extend', function(from) {
|
|
167
|
-
var props = Object.getOwnPropertyNames(from);
|
|
168
|
-
var dest = this;
|
|
169
|
-
props.forEach(function(name) {
|
|
170
|
-
if (name in dest) {
|
|
171
|
-
var destination = Object.getOwnPropertyDescriptor(from, name);
|
|
172
|
-
Object.defineProperty(dest, name, destination);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
dest[name] = from[name];
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
return this;
|
|
179
|
-
}); // Object.extend
|
|
180
|
-
|
|
181
|
-
extendObject('getProperties', function(){
|
|
182
|
-
var res = [];
|
|
183
|
-
for (var i in this)
|
|
184
|
-
if (this.hasOwnProperty(i))
|
|
185
|
-
res.push(this[i]);
|
|
186
|
-
return res;
|
|
187
|
-
}); // Object.getProperties
|
package/static/frontend.css
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
body { font:10pt verdana, arial, sans-serif; }
|
|
2
|
-
a img { border:0; } /* conform IE */
|
|
3
|
-
#items { list-style:none; padding:0; }
|
|
4
|
-
.full-label { position:absolute; padding-right:1em; text-align:left; }
|
|
5
|
-
|
|
6
|
-
/* tiles */
|
|
7
|
-
[mode=tiles] .item-link { float:left; width:9em; height:9em; overflow:hidden;
|
|
8
|
-
text-align:center; text-decoration:none;
|
|
9
|
-
margin:1px; /* reserve space for the border on hover */
|
|
10
|
-
}
|
|
11
|
-
[mode=tiles] .item-link:hover { background:#eee;
|
|
12
|
-
border:1px solid #ccc; margin:0; /* replace margin with border */
|
|
13
|
-
}
|
|
14
|
-
[mode=tiles] .item-label { display:block; padding:0 0.5em; margin:3px; word-wrap:break-word; }
|
|
15
|
-
[mode=tiles] .item-details { display:none; }
|
|
16
|
-
[mode=tiles] .item-link:hover + .item-details { display:block; float:left; }
|
|
17
|
-
[mode=tiles] .item-details-wrapper { position:absolute; background:#ffe; border:1px solid #eec; padding:0.2em 0.4em; }
|
|
18
|
-
[mode=tiles] .full-label { max-width:17em; }
|
|
19
|
-
|
|
20
|
-
/* list */
|
|
21
|
-
[mode=list] li { border-bottom:1px solid #eee; height:1.5em; }
|
|
22
|
-
[mode=list] li:nth-of-type(odd) { background:#fafafa; } /* stripes */
|
|
23
|
-
[mode=list] .item-link { clear:left; float:left; text-decoration:none;
|
|
24
|
-
width:20em; height:1.5em; overflow:hidden; margin-right:1em;
|
|
25
|
-
}
|
|
26
|
-
[mode=list] .item-link img { height:1.5em; vertical-align:middle; float:left; }
|
|
27
|
-
[mode=list] .item-label { margin-left:0.5em; margin-right:1em; white-space:nowrap; }
|
|
28
|
-
[mode=list] .item-type { display:none; }
|
|
29
|
-
[mode=list] .item-size { display:inline; }
|
package/static/frontend.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<title>HFS 3 front end</title>
|
|
6
|
-
<link rel="stylesheet" type="text/css" href="/~/frontend.css" />
|
|
7
|
-
|
|
8
|
-
<!--[if lt IE 9 ]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->
|
|
9
|
-
<script src='/socket.io/socket.io.js'></script>
|
|
10
|
-
<script src='/~/jquery.js'></script>
|
|
11
|
-
<script src='/~/extending.js'></script>
|
|
12
|
-
<script src='/~/misc.js'></script>
|
|
13
|
-
<script src='/~/frontend.js'></script>
|
|
14
|
-
<script src='/~/tpl.js'></script>
|
|
15
|
-
</head>
|
|
16
|
-
<body>
|
|
17
|
-
<h2>Folder <span id='folder'></span></h2>
|
|
18
|
-
<div id='folder-info'></div>
|
|
19
|
-
View mode <select id='mode'><option>tiles<option>list</select>
|
|
20
|
-
<p>Order <select id='order'><option value='' selected>none<option value='label'>name<option>type<option>size</select>
|
|
21
|
-
<ul id='items'></ul>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
package/static/frontend.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
var socket = io.connect(window.location.origin);
|
|
2
|
-
var currentFolder, listFromServer, foldersBefore=1;
|
|
3
|
-
|
|
4
|
-
// this object will hold all the customizable stuff, that is added in file "tpl.js"
|
|
5
|
-
var TPL = function(event) {
|
|
6
|
-
var fun = TPL[currentMode+'_'+event] || TPL[event];
|
|
7
|
-
if (!fun) return;
|
|
8
|
-
var newArgs = [];
|
|
9
|
-
for (var i=1,a=arguments,l=a.length; i<l; ++i)
|
|
10
|
-
newArgs.push(a[i]);
|
|
11
|
-
fun.apply(this, newArgs);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// understand the requested folder from the URL
|
|
15
|
-
function getURLfolder() {
|
|
16
|
-
var sub = location.hash.substr(1);
|
|
17
|
-
return sub.startsBy('/') ? sub : location.pathname+sub;
|
|
18
|
-
} // getURLfolder
|
|
19
|
-
|
|
20
|
-
$(function onJQ(){ // dom ready
|
|
21
|
-
socket.on('connect', function onIO(){ // socket ready
|
|
22
|
-
// try to restore last options
|
|
23
|
-
updateOrder(getCookie('order'));
|
|
24
|
-
updateMode(getCookie('mode'));
|
|
25
|
-
// change things at user will
|
|
26
|
-
$('#order').change(function(){ updateOrder(); redrawItems(); });
|
|
27
|
-
$('#mode').change(function(){ updateMode(); redrawItems(); });
|
|
28
|
-
|
|
29
|
-
loadFolder(getURLfolder(), function onFolder(){ // folder ready
|
|
30
|
-
|
|
31
|
-
/* support for the BACK button: when the user clicks the BACK button, the address bar changes going out of
|
|
32
|
-
sync with the view. We fix it ASAP. I don't know an event for the address bar, so i'm using an setInterval. */
|
|
33
|
-
setInterval(function onBackSupport(){
|
|
34
|
-
var shouldBe = getURLfolder();
|
|
35
|
-
if (currentFolder != shouldBe) {
|
|
36
|
-
loadFolder(shouldBe);
|
|
37
|
-
}
|
|
38
|
-
}, 300);
|
|
39
|
-
|
|
40
|
-
}); // don't redraw
|
|
41
|
-
});//socket connect
|
|
42
|
-
|
|
43
|
-
socket.on('vfs.changed', function(data){
|
|
44
|
-
log(data);
|
|
45
|
-
// it would be nicer to update only the changed item, but for now easily reload the whole dir
|
|
46
|
-
var folder = data.uri.substr(0, data.uri.lastIndexOf('/', data.uri.length-2)+1);
|
|
47
|
-
if (folder === currentFolder) {
|
|
48
|
-
loadFolder();
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// item hovering
|
|
53
|
-
$('.item-link').live({
|
|
54
|
-
mouseenter: function(){
|
|
55
|
-
if (!$(this).isOverflowed()) return; // fine!
|
|
56
|
-
// our label is clipped
|
|
57
|
-
var lbl = $(this).find('.item-label');
|
|
58
|
-
// make some changes so it's hopefully fully visible
|
|
59
|
-
lbl.addClass('full-label');
|
|
60
|
-
// if no bg was assigned, the enlarged label may overlap other elements, and its transparency may cause very bad readability
|
|
61
|
-
if (isTransparent(lbl.css('background-color'))) {
|
|
62
|
-
lbl.css('background-color', lbl.getClosestBackgroundColor() || '#fff')
|
|
63
|
-
.data('remove bg', true);
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
mouseleave: function(){
|
|
67
|
-
// undo changes made few lines above
|
|
68
|
-
var lbl = $(this).find('.full-label');
|
|
69
|
-
lbl.removeClass('full-label');
|
|
70
|
-
if (lbl.data('remove bg')) {
|
|
71
|
-
lbl.css('background-color','');
|
|
72
|
-
lbl.removeData('remove bg',null);
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
});//live
|
|
76
|
-
|
|
77
|
-
});//dom ready
|
|
78
|
-
|
|
79
|
-
// ask the server for the items list of the specified folder, then sort and display
|
|
80
|
-
function loadFolder(path /** optional */, cb /** optional */) {
|
|
81
|
-
if (path) currentFolder = path;
|
|
82
|
-
$('#folder').text(currentFolder);
|
|
83
|
-
socket.emit('get list', { path:currentFolder }, function onGetList(reply){
|
|
84
|
-
listFromServer = reply; // hold it in a global variable, to not loose it
|
|
85
|
-
convertList(reply);
|
|
86
|
-
$('#folder-info').html("number of items: "+reply.items.length);
|
|
87
|
-
sortItems();
|
|
88
|
-
redrawItems();
|
|
89
|
-
if (typeof cb == 'function') {
|
|
90
|
-
cb();
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
} // loadFolder
|
|
94
|
-
|
|
95
|
-
// convert the data: from object to array, so it can be sorted, and expands some field-names
|
|
96
|
-
function convertList(serverReply) {
|
|
97
|
-
var a = serverReply.items;
|
|
98
|
-
var clientFormat = [];
|
|
99
|
-
for (var k in a) {
|
|
100
|
-
var o = a[k];
|
|
101
|
-
renameProperties(o, {t:'type', s:'size'});
|
|
102
|
-
o.label = k;
|
|
103
|
-
switch (o.type) {
|
|
104
|
-
case undefined: // no type is default type: file
|
|
105
|
-
o.type = 'file';
|
|
106
|
-
case 'file': // for files, calculate specific type
|
|
107
|
-
o.type = nameToType(k) || o.type;
|
|
108
|
-
break;
|
|
109
|
-
case 'link':
|
|
110
|
-
o.url = o.resource;
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
o.url = o.url || encodeURI(currentFolder)+encodeURI(k)+(o.type == 'folder' ? '/' : '');
|
|
114
|
-
|
|
115
|
-
clientFormat.push(o);
|
|
116
|
-
}
|
|
117
|
-
serverReply.items = clientFormat;
|
|
118
|
-
} // convertList
|
|
119
|
-
|
|
120
|
-
// takes an object and renames some of its properties to the mapped names
|
|
121
|
-
function renameProperties(o, map) {
|
|
122
|
-
for (var from in map) {
|
|
123
|
-
var to = map[from];
|
|
124
|
-
if (!(from in o)) continue;
|
|
125
|
-
o[to] = o[from];
|
|
126
|
-
delete o[from];
|
|
127
|
-
}
|
|
128
|
-
} // renameProperties
|
|
129
|
-
|
|
130
|
-
// rebuild the DOM of items
|
|
131
|
-
function redrawItems() {
|
|
132
|
-
var x = $('#items').empty();
|
|
133
|
-
|
|
134
|
-
if (!listFromServer) return;
|
|
135
|
-
|
|
136
|
-
// add a link to the parent folder
|
|
137
|
-
var cf = currentFolder; // shortcut
|
|
138
|
-
if (cf > '/') {
|
|
139
|
-
addItem({
|
|
140
|
-
label: '↑↑',
|
|
141
|
-
url: cf.substr(0, 1+cf.lastIndexOf('/',cf.length-2)),
|
|
142
|
-
type: 'folder',
|
|
143
|
-
icon: 'folder'
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// put all the items. We don't support pagination yet
|
|
148
|
-
for (var i=0, a=listFromServer.items, l=a.length; i<l; ++i) {
|
|
149
|
-
var o = $.extend({}, a[i]); // clone. The item will be manipulated (also inside addItem), and we don't want to make this changes persistant over changes of the view mode
|
|
150
|
-
o.icon = o.type;
|
|
151
|
-
addItem(o);
|
|
152
|
-
}
|
|
153
|
-
} // redrawItems
|
|
154
|
-
|
|
155
|
-
// build the DOM for the single item, applying possible filtering functions
|
|
156
|
-
function addItem(it) {
|
|
157
|
-
it.extend({'icon-file':getIconURI(it.icon)}); // make this additions before the hook, so it can change these too
|
|
158
|
-
TPL('onObjectItem', it); // custom treatment, especially mode-based
|
|
159
|
-
$('<li>').append(TPL.item.format(it))
|
|
160
|
-
.appendTo('#items')
|
|
161
|
-
.find('a.item-link').click(itemClickHandler);
|
|
162
|
-
} // addItem
|
|
163
|
-
|
|
164
|
-
// called when an item is clicked
|
|
165
|
-
function itemClickHandler() {
|
|
166
|
-
var x = $(this);
|
|
167
|
-
var h = x.attr('href');
|
|
168
|
-
if (h.substr(-1) == '/') {
|
|
169
|
-
if (location.pathname != '/') { // reloads the page to have a neater URL
|
|
170
|
-
location = '/#'+h.substr(1);
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
location.hash = (h.startsBy(location.pathname)) ? h.substr(location.pathname.length) : h;
|
|
175
|
-
loadFolder(h);
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
if (!x.attr('target')) {
|
|
179
|
-
x.attr('target', 'preview'); // open the file in a new window so the app doesn't stop
|
|
180
|
-
}
|
|
181
|
-
return true;
|
|
182
|
-
} // itemClickHandler
|
|
183
|
-
|
|
184
|
-
function updateMode(v){
|
|
185
|
-
// if no value is passed, then read it from the DOM, otherwise write it in the DOM
|
|
186
|
-
if (!v || !v.length) v = $('#mode').val();
|
|
187
|
-
else $('#mode').val(v);
|
|
188
|
-
|
|
189
|
-
currentMode = v; // global
|
|
190
|
-
setCookie('mode', v); // remember
|
|
191
|
-
$('body').attr('mode', v);
|
|
192
|
-
} // updateMode
|
|
193
|
-
|
|
194
|
-
function updateOrder(v) {
|
|
195
|
-
// if no value is passed, then read it from the DOM, otherwise write it in the DOM
|
|
196
|
-
if (!v || !v.length) v = $('#order').val();
|
|
197
|
-
else $('#order').val(v);
|
|
198
|
-
|
|
199
|
-
currentOrder = v; // global
|
|
200
|
-
setCookie('order', v); // remember
|
|
201
|
-
if (v) {
|
|
202
|
-
$('#order option[value=]').remove(); // after we have sorted the items there's no way to return to the original order, so let's hide this option
|
|
203
|
-
}
|
|
204
|
-
sortItems();
|
|
205
|
-
} // updateOrder
|
|
206
|
-
|
|
207
|
-
function sortItems() {
|
|
208
|
-
if (!currentOrder || !listFromServer) return; // no job
|
|
209
|
-
|
|
210
|
-
listFromServer.items.sort(function cb(a,b,field){
|
|
211
|
-
field = field || currentOrder;
|
|
212
|
-
if (field != 'type' && foldersBefore) { // if field is 'type', then the folders are always put at the top
|
|
213
|
-
var res = -cmp(a['type'] == 'folder', b['type'] == 'folder');
|
|
214
|
-
if (res) return res;
|
|
215
|
-
}
|
|
216
|
-
var va = a[field];
|
|
217
|
-
var vb = b[field];
|
|
218
|
-
switch (field) {
|
|
219
|
-
case 'label':
|
|
220
|
-
va=va.low(), vb=vb.low();
|
|
221
|
-
break;
|
|
222
|
-
case 'type':
|
|
223
|
-
if (va == 'folder') va=''; // trick to get folders at the top
|
|
224
|
-
if (vb == 'folder') vb='';
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
return cmp(va,vb) || (field=='label' ? 0 : cb(a,b,'label'));
|
|
228
|
-
});
|
|
229
|
-
} // sortItems
|
|
230
|
-
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|